@edc-motor/ui 0.4.6 → 0.4.7

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": "@edc-motor/ui",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "EdC Motor — componentes públicos Vue 3 + tokens SCSS para webs de juegos de mesa (paquete fuente: lo compila el consumidor con Vite)",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
package/scss/_base.scss CHANGED
@@ -44,3 +44,14 @@ input[type='submit']:not(:disabled),
44
44
  input[type='file']:not(:disabled) {
45
45
  cursor: pointer;
46
46
  }
47
+
48
+ // Iconos del juego insertados por el wysiwyg (img.rt-icon): SIEMPRE al
49
+ // tamaño del texto que los rodea (1.2x), se rendericen donde se rendericen
50
+ // (con o sin .rich-content alrededor).
51
+ img.rt-icon {
52
+ display: inline-block;
53
+ width: 1.2em;
54
+ height: 1.2em;
55
+ vertical-align: -0.24em;
56
+ margin: 0 1px;
57
+ }
@@ -0,0 +1,39 @@
1
+ @use "../tokens" as *;
2
+
3
+ // Paginación compacta de listados (BasePagination.vue).
4
+ .base-pagination {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ gap: $space-2;
9
+
10
+ &__button {
11
+ display: inline-flex;
12
+ align-items: center;
13
+ justify-content: center;
14
+ width: 32px;
15
+ height: 32px;
16
+ background: none;
17
+ border: 1px solid $border;
18
+ border-radius: $radius-sm;
19
+ color: $text-2;
20
+ transition: color 0.15s ease, border-color 0.15s ease;
21
+
22
+ &:not(:disabled):hover {
23
+ color: $accent-500;
24
+ border-color: $accent-500;
25
+ }
26
+
27
+ &:disabled {
28
+ opacity: $disabled-opacity;
29
+ cursor: not-allowed;
30
+ }
31
+ }
32
+
33
+ &__status {
34
+ font-size: $fs-13;
35
+ color: $text-2;
36
+ min-width: 56px;
37
+ text-align: center;
38
+ }
39
+ }
@@ -4,6 +4,7 @@
4
4
  @use "motor-badge";
5
5
  @use "form-field";
6
6
  @use "base-select";
7
+ @use "base-pagination";
7
8
  @use "search-select";
8
9
  @use "blocks";
9
10
  @use "block-related";
@@ -45,9 +45,9 @@
45
45
  // Iconos del juego insertados en línea por el editor (<img class="rt-icon">).
46
46
  img.rt-icon {
47
47
  display: inline-block;
48
- width: 1.25em;
49
- height: 1.25em;
50
- vertical-align: -0.25em;
48
+ width: 1.2em;
49
+ height: 1.2em;
50
+ vertical-align: -0.24em;
51
51
  margin: 0 1px;
52
52
  }
53
53
  }
@@ -126,9 +126,9 @@
126
126
  // Iconos insertados: en línea con el texto.
127
127
  img.rt-icon {
128
128
  display: inline-block;
129
- width: 1.25em;
130
- height: 1.25em;
131
- vertical-align: -0.25em;
129
+ width: 1.2em;
130
+ height: 1.2em;
131
+ vertical-align: -0.24em;
132
132
  margin: 0 1px;
133
133
  }
134
134
 
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import { ChevronLeft, ChevronRight } from '@lucide/vue'
3
+
4
+ // Paginación compacta para listados (admin y web): anterior / "x de y" /
5
+ // siguiente. Con una sola página no pinta nada. Agnóstica de i18n (DC-29):
6
+ // textos por prop, defaults en castellano.
7
+ const props = withDefaults(
8
+ defineProps<{
9
+ page: number
10
+ pages: number
11
+ prevLabel?: string
12
+ nextLabel?: string
13
+ /** Texto accesible del estado, con {page} y {pages}. */
14
+ ofLabel?: string
15
+ }>(),
16
+ { prevLabel: 'Anterior', nextLabel: 'Siguiente', ofLabel: '{page} de {pages}' },
17
+ )
18
+
19
+ const emit = defineEmits<{ 'update:page': [page: number] }>()
20
+
21
+ function go(page: number) {
22
+ if (page < 1 || page > props.pages || page === props.page) return
23
+ emit('update:page', page)
24
+ }
25
+
26
+ function status(): string {
27
+ return props.ofLabel.replace('{page}', String(props.page)).replace('{pages}', String(props.pages))
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <nav v-if="pages > 1" class="base-pagination" :aria-label="status()">
33
+ <button
34
+ type="button"
35
+ class="base-pagination__button"
36
+ :disabled="page <= 1"
37
+ :aria-label="prevLabel"
38
+ :title="prevLabel"
39
+ @click="go(page - 1)"
40
+ >
41
+ <ChevronLeft :size="16" />
42
+ </button>
43
+ <span class="base-pagination__status">{{ status() }}</span>
44
+ <button
45
+ type="button"
46
+ class="base-pagination__button"
47
+ :disabled="page >= pages"
48
+ :aria-label="nextLabel"
49
+ :title="nextLabel"
50
+ @click="go(page + 1)"
51
+ >
52
+ <ChevronRight :size="16" />
53
+ </button>
54
+ </nav>
55
+ </template>
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export { default as IconButton } from './components/IconButton.vue'
7
7
  export { default as MotorBadge } from './components/MotorBadge.vue'
8
8
  export { default as BaseInput } from './components/BaseInput.vue'
9
9
  export { default as BaseTextarea } from './components/BaseTextarea.vue'
10
+ export { default as BasePagination } from './components/BasePagination.vue'
10
11
  export { default as BaseSelect, type SelectOption } from './components/BaseSelect.vue'
11
12
  export { default as SearchSelect, type SearchSelectOption } from './components/SearchSelect.vue'
12
13
  export { default as BaseCheckbox } from './components/BaseCheckbox.vue'