gitoriaLog in with ident

components

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit3bc905c53bc905c5components #15 (mission 003) 2/2: docs (README Look, STATUS, LOG), reportmre3bc905c5/components/pagination/pagination.hl

3.6 KB

  1. // pagination.hl — THE PAGINATION: "Previous 1 .. 44 45 46 .. 89 Next". Buttons for the first and last page, the current page
  2. // and its neighbours, "…" for the pages left out. Previous is missing on the first page, Next on the last. Plain Hybriel, no
  3. // script. The page reads `page` (1-based) and `pages` (how many there are) as its own members — set `pages` on the tag:
  4. // `Pagination { pages = 89 }`. USE ONE PER PAGE: a composed component's members are the page's state (COMPONENTS.md §12).
  5. // Every entry is a button (an `if` or a conditional attribute would re-create the DOM, hybriel#41); the "…" ones
  6. // only differ by class, and a click on them does nothing (a bound attribute like tabindex does not follow a reassigned list).
  7. Number page = 1
  8. Number pages = 10
  9. String previousLabel = 'Previous'
  10. String nextLabel = 'Next'
  11. Hybrid items = build(page, pages)
  12. entry(label, target, cls) {
  13. return { label = label target = target cls = cls }
  14. }
  15. // the page numbers to show: first, last, current ± 1; at either end four in a row; 0 = a gap
  16. numbers(p, n) {
  17. want = []
  18. let i = 1
  19. while (i <= n) {
  20. let near = i == 1 || i == n || (i >= p - 1 && i <= p + 1)
  21. if (p <= 3 && i <= 4) { near = true }
  22. if (p >= n - 2 && i >= n - 3) { near = true }
  23. if (near) { want.push(i) }
  24. i = i + 1
  25. }
  26. out = []
  27. let last = 0
  28. let k = 0
  29. while (k < want.length) {
  30. let v = want[k]
  31. if (v == last + 2) { out.push(v - 1) }
  32. else if (v > last + 2) { out.push(0) }
  33. out.push(v)
  34. last = v
  35. k = k + 1
  36. }
  37. return out
  38. }
  39. build(p, n) {
  40. out = []
  41. if (p > 1) { out.push(entry(previousLabel, p - 1, 'step')) }
  42. nums = numbers(p, n)
  43. let k = 0
  44. while (k < nums.length) {
  45. let v = nums[k]
  46. if (v == 0) { out.push(entry('…', 0, 'gap')) }
  47. else { out.push(entry('' + v, v, v == p ? 'page current' : 'page')) }
  48. k = k + 1
  49. }
  50. if (p < n) { out.push(entry(nextLabel, p + 1, 'step')) }
  51. return out
  52. }
  53. show(p) {
  54. if (p < 1 || p > pages) { return }
  55. page = p
  56. items = build(p, pages)
  57. }
  58. // Look: black, white and the greys #555 #999 #ddd #f2f2f2 (the library's base, named in shared/base.hl; README "Look"). Every colour is a semantic token
  59. // with its base value as fallback, `var(--color-…, #000)`, so a bare copy looks right and an app that declares the tokens (layouts.worldapi.org's
  60. // theme) restyles it. No frames: a border or ring only where it means something. A component's browser module
  61. // cannot import tokens itself.
  62. Style {
  63. pagination { display = 'block' }
  64. 'pagination ol' { display = 'flex' flexWrap = 'wrap' gap = '.3rem' margin = '0' padding = '0' listStyle = 'none' }
  65. 'pagination button' { font = 'inherit' fontWeight = '600' minWidth = '2.2rem' padding = '.35rem .6rem' color = 'var(--color-text, #000)' background = 'transparent' border = '0' borderRadius = '.4rem' cursor = 'pointer' }
  66. 'pagination button:hover' { background = 'var(--color-surface, #f2f2f2)' }
  67. 'pagination li.current button' { color = 'var(--color-accent-text, #fff)' background = 'var(--color-accent, #000)' border = '0' }
  68. 'pagination li.gap button' { color = 'var(--color-text-muted, #555)' background = 'transparent' border = '0' minWidth = '0' padding = '.35rem .2rem' cursor = 'default' pointerEvents = 'none' }
  69. }
  70. View {
  71. pagination {
  72. nav { title = "Pagination"
  73. ol { id = "pagination-items" for (it of items) { li { class = it.cls button { type = "button" class = "quiet" it.label on click(e) { emit paginationGo(e.target.textContent) } } } } }
  74. }
  75. }
  76. }
  77. // the click carries the button's text (a bound attribute does not follow a reassigned list, a text does)
  78. on paginationGo(text) {
  79. if (text == previousLabel) { show(page - 1) }
  80. else if (text == nextLabel) { show(page + 1) }
  81. else if (text != '…') { show(toNumber(text)) }
  82. }

Branches

Latest commits

  • 3bc905c5components #15 (mission 003) 2/2: docs (README Look, STATUS, LOG), reportmre
  • 5a98d77ecomponents #15 (mission 003) 1/2: black/white base look — greys for nuances, no WorldAPI fallbacks, no decorative frames; site + icon black/white; gate 230/0mre
  • 3f93d716components code order (mission 002) 4/4: docs, tests/letcount.py, tests/same-output*, reportmre
  • e747cfa0components code order (mission 002) 3/4: let only where reassigned (257 dropped, 0 never-reassigned left); gate 220/0, layouts gate 73/0, same outputmre
  • 172914a3components code order (mission 002) 2/4: lib/uploads.hl (demo upload storage), thin demo handlers, project.hl map; gate 220/0, same outputmre
  • d29f35b1components code order (mission 002) 1/4: styles.hl -> components/styles.hl; gate 220/0, same outputmre
  • 09945750components: Hybriel master 06617221 (plugin allocators 3a781359 + 413f60e4, http1 773de63e); gate 220/0mre
  • ede4d19acomponents: Hybriel master 190aa11d (fc838894 GC correctness, #126 closure scopes, #127); gate 220/0mre
  • 2bb9a935components: Hybriel master 8efba065 (re-vendor round 069: #126 memory, #48 lambda copy)mre
  • e4f01768antcolony#40: mission references point to the moved missionsmre
  • d32b44e2antcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
  • 0fb80b57components: Hybriel master ff51cf46 (re-vendor round)mre
  • 57408b6ecomponents#14: installable app (manifest, service worker, offline index), own iconmre
  • 317bd09fdeploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
  • becbd59bcomponents#13: modal dialog (<dialog> based, focus wrap, backdrop/Esc/x close with reason, scroll lock, footer buttons)mre
  • 367dd19adeploy.sh: never send .git or .gitignore to Byrodinmre
  • 4b4dabe5State of 2026-09-27, before the move to gitoriamre