@xoong/ui 0.0.42 → 0.0.44

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": "@xoong/ui",
3
- "version": "0.0.42",
3
+ "version": "0.0.44",
4
4
  "description": "xoong admin set: xoong.css tokens, <xo-table>, <xo-form>, <xo-dialog>, toast, confirm and a declarative History-API router. Depends on @xoong/core, @xoong/data and @xoong/forms.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -10,6 +10,7 @@
10
10
  "default": "./src/index.js"
11
11
  },
12
12
  "./table": "./src/table.js",
13
+ "./pager": "./src/pager.js",
13
14
  "./form": "./src/form.js",
14
15
  "./dialog": "./src/dialog.js",
15
16
  "./toast": "./src/toast.js",
@@ -20,9 +21,9 @@
20
21
  "sideEffects": true,
21
22
  "license": "MIT",
22
23
  "dependencies": {
23
- "@xoong/core": "0.0.42",
24
- "@xoong/data": "0.0.42",
25
- "@xoong/forms": "0.0.42"
24
+ "@xoong/core": "0.0.44",
25
+ "@xoong/data": "0.0.44",
26
+ "@xoong/forms": "0.0.44"
26
27
  },
27
28
  "files": [
28
29
  "src"
package/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // Importing the package registers every element of the admin set.
2
2
  import '@xoong/forms'; // every <form xo-submit> (and <xo-form>) uses the schema-driven form model
3
3
  import './table.js';
4
+ import './pager.js';
4
5
  import './form.js';
5
6
  import './dialog.js';
6
7
  import './toast.js';
package/src/mist.css CHANGED
@@ -1375,6 +1375,8 @@
1375
1375
  .xo-input-wrap button.xo-date-open { position: absolute; }
1376
1376
  xo-image {
1377
1377
  border-radius: var(--xo-radius);
1378
+ }
1379
+ xo-image[data-state="empty"], xo-image[data-state="error"] {
1378
1380
  background: var(--xo-color-subtle);
1379
1381
  }
1380
1382
  xo-image[data-state="loading"] {
@@ -1468,6 +1470,7 @@
1468
1470
  .xo-file-list li { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border: 1px solid var(--xo-color-border); border-radius: var(--xo-radius); background: var(--xo-color-surface); font-size: 14px; }
1469
1471
  .xo-file-list li img { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; flex: none; }
1470
1472
  .xo-file-list li span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1473
+ xo-menu:not(:defined) > :not([xo-menu-trigger]) { display: none; }
1471
1474
 
1472
1475
  /* ---- skin ---- */
1473
1476
  :root { --shadow-sm: 0 1px 2px color-mix(in srgb, var(--xo-color-text) 6%, transparent); --shadow-float: 0 12px 32px color-mix(in srgb, var(--xo-color-text) 14%, transparent), 0 2px 6px color-mix(in srgb, var(--xo-color-text) 8%, transparent); --xo-shadow-pop: var(--shadow-float); --xo-shadow-raised: none; --xo-focus: 2px solid var(--xo-color-accent); --xo-focus-thin: 2px solid var(--xo-color-accent); }
package/src/pager.js ADDED
@@ -0,0 +1,34 @@
1
+ // @ts-check
2
+ /**
3
+ * <xo-pager page-size="12" page-sizes="12,24,48"></xo-pager>: Previous and Next for any list in the enclosing <xo-view> (a tile grid, a thread
4
+ * list), the same pager <xo-table page-size> draws under its table.
5
+ *
6
+ * - page-size: rows per page; sets `limit`, and the buttons change `offset`. The operation must declare `limit` and `offset`, and the response
7
+ * needs a `total` field for the "1–12 of 48" text and for the end of the list.
8
+ * - page-sizes="12,24,48": a rows-per-page choice.
9
+ * - Draws `nav.xo-pager` (`span.xo-range`, `select.xo-page-size`, two buttons); Previous shows while `$hasPrev`, Next while `$hasNext`.
10
+ */
11
+ import { defineTemplate } from '@xoong/data/view';
12
+
13
+ const esc = (/** @type {string} */ s) => s.replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c] ?? c);
14
+
15
+ /** The pager markup (also used by <xo-table>). @param {{ pageSize: number, sizes?: string[] }} options */
16
+ export function pagerMarkup({ pageSize, sizes = [] }) {
17
+ return `
18
+ <nav class="xo-pager" aria-label="Pagination" xo-t="aria-label:xoong.table.pagination">
19
+ <span class="xo-range" xo-if="total" xo-t="xoong.table.range">{$from}–{$to} of {total}</span>${sizes.length ? `
20
+ <select class="xo-page-size" xo-param="limit" aria-label="Rows per page" xo-t="aria-label:xoong.table.rowsPerPage">${sizes.map((s) => `<option value="${esc(s)}">${esc(s)}</option>`).join('')}</select>` : ''}
21
+ <button type="button" xo-if="$hasPrev" xo-param="offset-=${pageSize}" xo-t="xoong.table.previous">Previous</button>
22
+ <button type="button" xo-if="$hasNext" xo-param="offset+=${pageSize}" xo-t="xoong.table.next">Next</button>
23
+ </nav>`;
24
+ }
25
+
26
+ defineTemplate('xo-pager', (el, { host }) => {
27
+ const pageSize = Number(el.getAttribute('page-size')) || 25;
28
+ if (host.params.limit == null) host.params = { ...host.params, limit: pageSize }; // the view asks for one page
29
+ const sizes = (el.getAttribute('page-sizes') || '').split(',').map((s) => s.trim()).filter(Boolean);
30
+ const box = document.createElement('div');
31
+ box.style.display = 'contents'; // the pager sits where the element was, in the layout of its parent
32
+ box.innerHTML = pagerMarkup({ pageSize, sizes });
33
+ return box;
34
+ });
package/src/table.js CHANGED
@@ -23,6 +23,7 @@
23
23
  * The operation must declare those query parameters; `xoong check` reports it when it does not (XO250).
24
24
  */
25
25
  import { defineTemplate } from '@xoong/data/view';
26
+ import { pagerMarkup } from './pager.js';
26
27
 
27
28
  const esc = (s) => s.replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]);
28
29
 
@@ -68,12 +69,6 @@ defineTemplate('xo-table', (el, { host }) => {
68
69
  <thead><tr>${tickAll}${head}${actions ? '<th scope="col"><span class="xo-visually-hidden" xo-t="xoong.table.actions">Actions</span></th>' : ''}</tr></thead>
69
70
  <tbody><tr xo-each="${esc(of)}">${tickRow}${cells}${actions ?`<td class="xo-actions">${actions}</td>` : ''}</tr></tbody>
70
71
  </table>${empty ? `
71
- <div class="xo-empty" xo-if="!${esc(of)}"><div xo-if="!$loading"><div xo-if="!$error">${empty}</div></div></div>` : ''}${pageSize ? `
72
- <nav class="xo-pager" aria-label="Pagination" xo-t="aria-label:xoong.table.pagination">
73
- <span class="xo-range" xo-if="total" xo-t="xoong.table.range">{$from}–{$to} of {total}</span>${sizes.length ? `
74
- <select class="xo-page-size" xo-param="limit" aria-label="Rows per page" xo-t="aria-label:xoong.table.rowsPerPage">${sizes.map((s) => `<option value="${esc(s)}">${esc(s)}</option>`).join('')}</select>` : ''}
75
- <button type="button" xo-if="$hasPrev" xo-param="offset-=${pageSize}" xo-t="xoong.table.previous">Previous</button>
76
- <button type="button" xo-if="$hasNext" xo-param="offset+=${pageSize}" xo-t="xoong.table.next">Next</button>
77
- </nav>` : ''}`;
72
+ <div class="xo-empty" xo-if="!${esc(of)}"><div xo-if="!$loading"><div xo-if="!$error">${empty}</div></div></div>` : ''}${pageSize ? pagerMarkup({ pageSize, sizes }) : ''}`;
78
73
  return box;
79
74
  });
package/src/xoong.css CHANGED
@@ -112,7 +112,7 @@
112
112
  .xo-table .xo-actions > * + * { margin-inline-start: var(--xo-space-2); }
113
113
  .xo-bulk { display: flex; align-items: center; gap: var(--xo-space-2); padding: var(--xo-space-2); background: var(--xo-color-bg); border-bottom: 1px solid var(--xo-color-border); }
114
114
  .xo-filters { display: flex; flex-wrap: wrap; gap: var(--xo-space-2); padding: var(--xo-space-2); border-bottom: 1px solid var(--xo-color-border); }
115
- .xo-toast { position: fixed; inset-block-end: var(--xo-space-4); inset-inline-end: var(--xo-space-4); max-width: 24rem; margin: 0; padding: var(--xo-space-2) var(--xo-space-3); color: var(--xo-color-danger); background: var(--xo-color-surface); border: 1px solid var(--xo-color-danger); border-radius: var(--xo-radius); }
115
+ .xo-toast { z-index: var(--xo-z-toast, 60); position: fixed; inset-block-end: var(--xo-space-4); inset-inline-end: var(--xo-space-4); max-width: 24rem; margin: 0; padding: var(--xo-space-2) var(--xo-space-3); color: var(--xo-color-danger); background: var(--xo-color-surface); border: 1px solid var(--xo-color-danger); border-radius: var(--xo-radius); }
116
116
  .xo-toast[hidden] { display: none; }
117
117
  .xo-pager { display: flex; gap: var(--xo-space-2); justify-content: flex-end; padding: var(--xo-space-2); }
118
118