@inglorious/ui 8.2.0 → 8.2.1

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": "@inglorious/ui",
3
- "version": "8.2.0",
3
+ "version": "8.2.1",
4
4
  "description": "A design system for Inglorious Web with render-function components and customizable themes",
5
5
  "author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -321,6 +321,7 @@
321
321
  "happy-dom": "^20.14.0",
322
322
  "jsdom": "^30.0.1",
323
323
  "prettier": "^3.9.6",
324
+ "remark-gfm": "^4.0.1",
324
325
  "storybook": "^10.6.0",
325
326
  "vite": "^8.2.2",
326
327
  "vitest": "^5.0.0"
@@ -9,7 +9,7 @@ import {
9
9
  } from "../../stories/notifyStory.js"
10
10
  import { Icon } from "."
11
11
 
12
- const unicodeList = {
12
+ const UnicodeList = {
13
13
  ...VirtualList,
14
14
 
15
15
  create(entity) {
@@ -38,7 +38,7 @@ const unicodeList = {
38
38
  render(entity, api) {
39
39
  return VirtualList.render(entity, {
40
40
  ...api,
41
- getType: () => unicodeList,
41
+ getType: () => UnicodeList,
42
42
  })
43
43
  },
44
44
 
@@ -88,7 +88,7 @@ const unicodeList = {
88
88
 
89
89
  export default {
90
90
  title: "Data Display/Icon",
91
- render: createEntityRender({ unicodeList }),
91
+ render: createEntityRender({ UnicodeList }),
92
92
  argTypes: {
93
93
  ...notifyActionArgType,
94
94
  start: {
@@ -45,12 +45,17 @@ export function scroll(entity, containerEl) {
45
45
  */
46
46
  export function mount(entity, containerEl) {
47
47
  const firstItem = containerEl.querySelector("[data-index]")
48
- if (!firstItem) return
48
+ // A list not laid out yet, such as one rendered into a detached element,
49
+ // measures 0: keep the estimate, and measure again on a later render.
50
+ if (!firstItem?.offsetHeight) return
49
51
 
50
52
  entity.itemHeight = firstItem.offsetHeight
51
53
  entity.visibleRange = {
52
54
  start: 0,
53
- end: Math.ceil(entity.viewportHeight / entity.itemHeight),
55
+ end: Math.min(
56
+ Math.ceil(entity.viewportHeight / entity.itemHeight),
57
+ entity.items?.length ?? Infinity,
58
+ ),
54
59
  }
55
60
  }
56
61
 
@@ -11,6 +11,31 @@ import { styleMap } from "@inglorious/web/directives/style-map"
11
11
 
12
12
  const PRETTY_INDEX = 1
13
13
 
14
+ // The list elements already being measured. Every update re-renders, and
15
+ // measuring is an update, so measuring on each render would loop forever.
16
+ const measured = new WeakSet()
17
+
18
+ /**
19
+ * Notifies `mount` once per list element, after a frame and once it is in the
20
+ * document: before that it has no layout to measure.
21
+ * @param {HTMLElement} el
22
+ * @param {VirtualListEntity} entity
23
+ * @param {Api} api
24
+ */
25
+ function measureOnce(el, entity, api) {
26
+ if (measured.has(el)) return
27
+ measured.add(el)
28
+
29
+ const measure = () => {
30
+ if (!el.isConnected) {
31
+ requestAnimationFrame(measure)
32
+ return
33
+ }
34
+ api.notify(`#${entity.id}:mount`, el)
35
+ }
36
+ requestAnimationFrame(measure)
37
+ }
38
+
14
39
  /**
15
40
  * Renders a virtualized list that only mounts visible items for performance.
16
41
  * Uses item height estimates to compute scroll ranges and notifies on mount/scroll.
@@ -49,11 +74,7 @@ export function render(entity, api) {
49
74
  style=${styleMap({ height: `${viewportHeight}px`, overflow: "auto" })}
50
75
  @scroll=${(e) => api.notify(`#${entity.id}:scroll`, e.currentTarget)}
51
76
  ${ref((el) => {
52
- if (el && !itemHeight) {
53
- queueMicrotask(() => {
54
- api.notify(`#${entity.id}:mount`, el)
55
- })
56
- }
77
+ if (el && !itemHeight) measureOnce(el, entity, api)
57
78
  })}
58
79
  >
59
80
  <div