gridsmith-ui 0.31.1 → 0.32.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.
- package/CHANGELOG.md +46 -1
- package/dist/charts.d.ts +101 -30
- package/dist/charts.js +180 -105
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +6 -6
- package/dist/{chunk-EZ3ZGFGA.js → chunk-2724SJO2.js} +12 -4
- package/dist/chunk-2724SJO2.js.map +1 -0
- package/dist/{chunk-IZW5XHKA.js → chunk-DO6DLTFK.js} +10 -8
- package/dist/chunk-DO6DLTFK.js.map +1 -0
- package/dist/{chunk-KSJTMSYA.js → chunk-H732QL56.js} +4 -4
- package/dist/{chunk-KSJTMSYA.js.map → chunk-H732QL56.js.map} +1 -1
- package/dist/{chunk-DR6WEI3A.js → chunk-HCEHTJ5E.js} +3 -3
- package/dist/{chunk-DR6WEI3A.js.map → chunk-HCEHTJ5E.js.map} +1 -1
- package/dist/{chunk-2TCCSKL3.js → chunk-HUVZQOU4.js} +5 -5
- package/dist/{chunk-2TCCSKL3.js.map → chunk-HUVZQOU4.js.map} +1 -1
- package/dist/{chunk-TH272DIC.js → chunk-JHZ22HQP.js} +75 -24
- package/dist/chunk-JHZ22HQP.js.map +1 -0
- package/dist/{chunk-I6JJ7KKP.js → chunk-NGZJK57C.js} +14 -10
- package/dist/chunk-NGZJK57C.js.map +1 -0
- package/dist/{chunk-BHTAVJIG.js → chunk-OVHM55JF.js} +5 -5
- package/dist/{chunk-BHTAVJIG.js.map → chunk-OVHM55JF.js.map} +1 -1
- package/dist/{chunk-NDL2JGQ7.js → chunk-QY2RA2HO.js} +5 -5
- package/dist/{chunk-NDL2JGQ7.js.map → chunk-QY2RA2HO.js.map} +1 -1
- package/dist/{chunk-W3GY5ROH.js → chunk-R2IAK3J3.js} +3 -3
- package/dist/{chunk-W3GY5ROH.js.map → chunk-R2IAK3J3.js.map} +1 -1
- package/dist/{chunk-V73LHNRL.js → chunk-RS624TD5.js} +29 -10
- package/dist/chunk-RS624TD5.js.map +1 -0
- package/dist/{chunk-IOHGE4EW.js → chunk-SIEU4H3H.js} +8 -8
- package/dist/chunk-SIEU4H3H.js.map +1 -0
- package/dist/{chunk-DBHVJ7Z3.js → chunk-SS3C24IJ.js} +3 -2
- package/dist/chunk-SS3C24IJ.js.map +1 -0
- package/dist/{chunk-K3NAFQ4S.js → chunk-TMPPBXX3.js} +3 -3
- package/dist/{chunk-K3NAFQ4S.js.map → chunk-TMPPBXX3.js.map} +1 -1
- package/dist/{chunk-SLGGZ3MU.js → chunk-WSKPESAX.js} +12 -10
- package/dist/chunk-WSKPESAX.js.map +1 -0
- package/dist/{chunk-HQFTP7Y5.js → chunk-XBVZIN26.js} +4 -4
- package/dist/{chunk-HQFTP7Y5.js.map → chunk-XBVZIN26.js.map} +1 -1
- package/dist/data-grid.js +9 -9
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +2 -2
- package/dist/editor.js +3 -2
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +44 -6
- package/dist/index.js +436 -213
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +9 -9
- package/dist/resizable.d.ts +11 -2
- package/dist/resizable.js +96 -22
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +2 -2
- package/dist/tokens.css +6 -6
- package/dist/virtualized.js +9 -8
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +6 -6
- package/package.json +1 -1
- package/dist/chunk-DBHVJ7Z3.js.map +0 -1
- package/dist/chunk-EZ3ZGFGA.js.map +0 -1
- package/dist/chunk-I6JJ7KKP.js.map +0 -1
- package/dist/chunk-IOHGE4EW.js.map +0 -1
- package/dist/chunk-IZW5XHKA.js.map +0 -1
- package/dist/chunk-SLGGZ3MU.js.map +0 -1
- package/dist/chunk-TH272DIC.js.map +0 -1
- package/dist/chunk-V73LHNRL.js.map +0 -1
package/dist/tokens.css
CHANGED
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
152
152
|
--ds-nav-h-track-gap: 0px;
|
|
153
153
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
154
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
154
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
155
155
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
156
156
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
157
157
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
160
160
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
161
161
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
162
|
-
--ds-tree-active-bg: var(--ds-
|
|
162
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
163
163
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
164
164
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
165
165
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
185
185
|
--ds-nav-h-track-gap: 0px;
|
|
186
186
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
187
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
187
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
188
188
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
189
189
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
190
190
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
193
193
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
194
194
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
195
|
-
--ds-tree-active-bg: var(--ds-
|
|
195
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
196
196
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
197
197
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
198
198
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
|
@@ -469,7 +469,7 @@
|
|
|
469
469
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
470
470
|
--ds-nav-h-track-gap: 0px;
|
|
471
471
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
472
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
472
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
473
473
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
474
474
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
475
475
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -477,7 +477,7 @@
|
|
|
477
477
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
478
478
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
479
479
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
480
|
-
--ds-tree-active-bg: var(--ds-
|
|
480
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
481
481
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
482
482
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
483
483
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
package/dist/virtualized.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useKeyboardScroll } from './chunk-
|
|
3
|
-
import { useWholeListCheck, pagerPart, Pagination } from './chunk-
|
|
2
|
+
import { useKeyboardScroll } from './chunk-H732QL56.js';
|
|
3
|
+
import { useWholeListCheck, pagerPart, Pagination } from './chunk-SIEU4H3H.js';
|
|
4
4
|
import './chunk-QOMP4D6V.js';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-DO6DLTFK.js';
|
|
6
6
|
import './chunk-7QLXYRPD.js';
|
|
7
7
|
import './chunk-72SDAX54.js';
|
|
8
|
-
import { useScrollsInside } from './chunk-
|
|
9
|
-
import './chunk-
|
|
8
|
+
import { useScrollsInside, useRunsEdgeToEdge } from './chunk-RS624TD5.js';
|
|
9
|
+
import './chunk-XBVZIN26.js';
|
|
10
10
|
import './chunk-7RKC5C7G.js';
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
11
|
+
import './chunk-R2IAK3J3.js';
|
|
12
|
+
import './chunk-HCEHTJ5E.js';
|
|
13
13
|
import './chunk-53F7GVBQ.js';
|
|
14
|
-
import { useLatest, cn, FOCUS_INSET } from './chunk-
|
|
14
|
+
import { useLatest, cn, FOCUS_INSET } from './chunk-2724SJO2.js';
|
|
15
15
|
import { useRef, useState, useCallback, useEffect } from 'react';
|
|
16
16
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
17
17
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -28,6 +28,7 @@ function VirtualizedList({
|
|
|
28
28
|
"aria-label": ariaLabel = "List"
|
|
29
29
|
}) {
|
|
30
30
|
useScrollsInside();
|
|
31
|
+
useRunsEdgeToEdge();
|
|
31
32
|
const parentRef = useRef(null);
|
|
32
33
|
const endRef = useRef(null);
|
|
33
34
|
const [scroller, setScroller] = useState(null);
|
package/dist/virtualized.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/components/VirtualizedList.tsx"],"names":[],"mappings":"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","file":"virtualized.js","sourcesContent":["import { useCallback, useEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { useVirtualizer, type VirtualItem } from \"@tanstack/react-virtual\";\nimport { cn, FOCUS_INSET } from \"../lib/utils\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { Pagination } from \"./Pagination\";\nimport { pagerPart, useWholeListCheck, type Pager } from \"../lib/use-pagination\";\nimport { useScrollsInside } from \"../lib/surface-context\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\n\nexport interface VirtualizedListProps<T> {\n items: T[];\n estimateSize: (index: number) => number;\n /** An item, with its index in `items` (the whole list, when the list is paged). */\n renderItem: (item: T, index: number, virtualItem: VirtualItem) => ReactNode;\n overscan?: number;\n height?: number | string;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n /**\n * The list's pager (Sprint 25.13 A49): paging and drawing only the rows on screen combine. Pass every item and\n * `usePagination(items)`'s pager: the list mounts only the rows on screen of the pager's part, and beneath it draws the\n * control in the project's style. A new page starts at its top; with infinite scroll, scrolling inside the list loads\n * more. For a long page (logs, feeds) the user asked to page differently, pass the size to the hook\n * (`usePagination(rows, { pageSize: 100 })`) with its override note.\n */\n pager?: Pager<unknown>;\n /**\n * The list's name, for the Tab stop it becomes while it scrolls with nothing inside to Tab to (Sprint 25.29 item 10):\n * what it lists (\"Activity log\"). Default \"List\".\n */\n \"aria-label\"?: string;\n}\n\nexport function VirtualizedList<T>({\n items: allItems,\n estimateSize,\n renderItem,\n overscan = 5,\n height = 400,\n className,\n ref,\n pager,\n \"aria-label\": ariaLabel = \"List\",\n}: VirtualizedListProps<T>) {\n // Sprint 25.14 A44: a list with no frame of its own: a SplitView's list pane keeps its hairline around it\n useScrollsInside();\n const parentRef = useRef<HTMLDivElement>(null);\n const endRef = useRef<HTMLDivElement>(null);\n // what the keyboard reaches in a row comes into view whole, with its outline (Sprint 30, P3: useKeyboardScroll reveals it)\n const [scroller, setScroller] = useState<HTMLDivElement | null>(null);\n // a list with nothing inside to Tab to, scrolling, is a Tab stop of its own, named (Sprint 25.29 item 10)\n useKeyboardScroll(scroller, ariaLabel);\n const setList = useCallback((node: HTMLDivElement | null) => {\n (parentRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n setScroller(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }, [ref]);\n useWholeListCheck(\"VirtualizedList\", allItems.length, pager);\n const items = pagerPart(allItems, pager);\n const offset = pager ? Math.max(0, pager.range[0] - 1) : 0;\n\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Virtual is not compiler-compatible (informational; the project does not use the React Compiler)\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: (index) => estimateSize(offset + index),\n // a row is known by its place in the whole list, so page 2's third row isn't page 1's (the review of 30 September:\n // an entry opened on page 1 showed opened on page 2, and page 1's heights carried over)\n getItemKey: (index) => offset + index,\n overscan,\n });\n\n // A49: a new page starts at its top, and so does a growing list that starts again at its first page (a new order, a\n // search): left scrolled to its end, it loaded the next page at once (the review of 30 September)\n const page = pager ? pager.page : null;\n const pageBefore = useRef(page);\n const numbered = pager?.style === \"pagination\";\n useEffect(() => {\n const before = pageBefore.current;\n pageBefore.current = page;\n if (page === null || !parentRef.current) return;\n if (numbered ? page !== before : before !== null && page < before) parentRef.current.scrollTop = 0;\n }, [page, numbered]);\n\n // A49: with infinite scroll, the trigger sits at the end of the list's own content and watches the list's scroller\n // (it watched the viewport, so scrolling inside the list never loaded more); it loads once per growth of the list\n const loadMore = useLatest(pager?.loadMore);\n const growing = pager?.style === \"infinite-scroll\" && pager.hasMore;\n const loadedAt = useRef(-1);\n useEffect(() => {\n const root = parentRef.current;\n const end = endRef.current;\n // the list's length changed since the last load (it grew, or started again at page 1): it may load again (the\n // review of 30 September: after a reset to the first page it never loaded again)\n if (loadedAt.current !== items.length) loadedAt.current = -1;\n if (!growing || !root || !end || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver((entries) => {\n if (!entries.some((e) => e.isIntersecting) || loadedAt.current === items.length) return;\n loadedAt.current = items.length;\n loadMore.current?.();\n }, { root, rootMargin: \"200px 0px\" });\n observer.observe(end);\n return () => observer.disconnect();\n }, [growing, items.length, loadMore]);\n\n const list = (\n <div\n ref={setList}\n data-ds-list={pager ? \"\" : undefined}\n className={cn(\n \"overflow-auto scroll-p-[4px]\",\n FOCUS_INSET,\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"bg-[var(--ds-bg-surface)]\",\n !pager && className,\n )}\n style={{ height }}\n >\n <div className=\"relative w-full\" style={{ height: virtualizer.getTotalSize() }}>\n {virtualizer.getVirtualItems().map((virtualItem) => (\n <div\n key={virtualItem.key}\n data-index={virtualItem.index}\n ref={virtualizer.measureElement}\n className=\"absolute top-0 left-0 w-full\"\n style={{ transform: `translateY(${virtualItem.start}px)` }}\n >\n {renderItem(items[virtualItem.index], offset + virtualItem.index, virtualItem)}\n </div>\n ))}\n </div>\n {growing && <div ref={endRef} data-load-more-trigger=\"\" aria-hidden=\"true\" className=\"h-px w-full\" />}\n </div>\n );\n // A3: the pager's control is the list's next sibling, as <Pagination {...pager.props} /> would be. With infinite\n // scroll it is the Load more button alone, for keyboard users: the list's own trigger loads as it scrolls (A49). The\n // two are one element, which takes the className, so in a grid or a flex row they stay one item, and the list keeps\n // its element while its items come and go (the review of 30 September).\n if (!pager) return list;\n return (\n <div data-gs-paged=\"\" className={cn(\"flex flex-col min-w-0\", className)}>\n {list}\n {allItems.length > 0 && <Pagination {...pager.props} mode={pager.style === \"infinite-scroll\" ? \"load-more\" : pager.props.mode} />}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/components/VirtualizedList.tsx"],"names":[],"mappings":"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","file":"virtualized.js","sourcesContent":["import { useCallback, useEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { useVirtualizer, type VirtualItem } from \"@tanstack/react-virtual\";\nimport { cn, FOCUS_INSET } from \"../lib/utils\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { Pagination } from \"./Pagination\";\nimport { pagerPart, useWholeListCheck, type Pager } from \"../lib/use-pagination\";\nimport { useRunsEdgeToEdge, useScrollsInside } from \"../lib/surface-context\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\n\nexport interface VirtualizedListProps<T> {\n items: T[];\n estimateSize: (index: number) => number;\n /** An item, with its index in `items` (the whole list, when the list is paged). */\n renderItem: (item: T, index: number, virtualItem: VirtualItem) => ReactNode;\n overscan?: number;\n height?: number | string;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n /**\n * The list's pager (Sprint 25.13 A49): paging and drawing only the rows on screen combine. Pass every item and\n * `usePagination(items)`'s pager: the list mounts only the rows on screen of the pager's part, and beneath it draws the\n * control in the project's style. A new page starts at its top; with infinite scroll, scrolling inside the list loads\n * more. For a long page (logs, feeds) the user asked to page differently, pass the size to the hook\n * (`usePagination(rows, { pageSize: 100 })`) with its override note.\n */\n pager?: Pager<unknown>;\n /**\n * The list's name, for the Tab stop it becomes while it scrolls with nothing inside to Tab to (Sprint 25.29 item 10):\n * what it lists (\"Activity log\"). Default \"List\".\n */\n \"aria-label\"?: string;\n}\n\nexport function VirtualizedList<T>({\n items: allItems,\n estimateSize,\n renderItem,\n overscan = 5,\n height = 400,\n className,\n ref,\n pager,\n \"aria-label\": ariaLabel = \"List\",\n}: VirtualizedListProps<T>) {\n // Sprint 25.14 A44: a list with no frame of its own: a SplitView's list pane keeps its hairline around it\n useScrollsInside();\n // Sprint 25.33 C1: its rows are full-width bands, so the list pane holding it is flush\n useRunsEdgeToEdge();\n const parentRef = useRef<HTMLDivElement>(null);\n const endRef = useRef<HTMLDivElement>(null);\n // what the keyboard reaches in a row comes into view whole, with its outline (Sprint 30, P3: useKeyboardScroll reveals it)\n const [scroller, setScroller] = useState<HTMLDivElement | null>(null);\n // a list with nothing inside to Tab to, scrolling, is a Tab stop of its own, named (Sprint 25.29 item 10)\n useKeyboardScroll(scroller, ariaLabel);\n const setList = useCallback((node: HTMLDivElement | null) => {\n (parentRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n setScroller(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }, [ref]);\n useWholeListCheck(\"VirtualizedList\", allItems.length, pager);\n const items = pagerPart(allItems, pager);\n const offset = pager ? Math.max(0, pager.range[0] - 1) : 0;\n\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Virtual is not compiler-compatible (informational; the project does not use the React Compiler)\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: (index) => estimateSize(offset + index),\n // a row is known by its place in the whole list, so page 2's third row isn't page 1's (the review of 30 September:\n // an entry opened on page 1 showed opened on page 2, and page 1's heights carried over)\n getItemKey: (index) => offset + index,\n overscan,\n });\n\n // A49: a new page starts at its top, and so does a growing list that starts again at its first page (a new order, a\n // search): left scrolled to its end, it loaded the next page at once (the review of 30 September)\n const page = pager ? pager.page : null;\n const pageBefore = useRef(page);\n const numbered = pager?.style === \"pagination\";\n useEffect(() => {\n const before = pageBefore.current;\n pageBefore.current = page;\n if (page === null || !parentRef.current) return;\n if (numbered ? page !== before : before !== null && page < before) parentRef.current.scrollTop = 0;\n }, [page, numbered]);\n\n // A49: with infinite scroll, the trigger sits at the end of the list's own content and watches the list's scroller\n // (it watched the viewport, so scrolling inside the list never loaded more); it loads once per growth of the list\n const loadMore = useLatest(pager?.loadMore);\n const growing = pager?.style === \"infinite-scroll\" && pager.hasMore;\n const loadedAt = useRef(-1);\n useEffect(() => {\n const root = parentRef.current;\n const end = endRef.current;\n // the list's length changed since the last load (it grew, or started again at page 1): it may load again (the\n // review of 30 September: after a reset to the first page it never loaded again)\n if (loadedAt.current !== items.length) loadedAt.current = -1;\n if (!growing || !root || !end || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver((entries) => {\n if (!entries.some((e) => e.isIntersecting) || loadedAt.current === items.length) return;\n loadedAt.current = items.length;\n loadMore.current?.();\n }, { root, rootMargin: \"200px 0px\" });\n observer.observe(end);\n return () => observer.disconnect();\n }, [growing, items.length, loadMore]);\n\n const list = (\n <div\n ref={setList}\n data-ds-list={pager ? \"\" : undefined}\n className={cn(\n \"overflow-auto scroll-p-[4px]\",\n FOCUS_INSET,\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"bg-[var(--ds-bg-surface)]\",\n !pager && className,\n )}\n style={{ height }}\n >\n <div className=\"relative w-full\" style={{ height: virtualizer.getTotalSize() }}>\n {virtualizer.getVirtualItems().map((virtualItem) => (\n <div\n key={virtualItem.key}\n data-index={virtualItem.index}\n ref={virtualizer.measureElement}\n className=\"absolute top-0 left-0 w-full\"\n style={{ transform: `translateY(${virtualItem.start}px)` }}\n >\n {renderItem(items[virtualItem.index], offset + virtualItem.index, virtualItem)}\n </div>\n ))}\n </div>\n {growing && <div ref={endRef} data-load-more-trigger=\"\" aria-hidden=\"true\" className=\"h-px w-full\" />}\n </div>\n );\n // A3: the pager's control is the list's next sibling, as <Pagination {...pager.props} /> would be. With infinite\n // scroll it is the Load more button alone, for keyboard users: the list's own trigger loads as it scrolls (A49). The\n // two are one element, which takes the className, so in a grid or a flex row they stay one item, and the list keeps\n // its element while its items come and go (the review of 30 September).\n if (!pager) return list;\n return (\n <div data-gs-paged=\"\" className={cn(\"flex flex-col min-w-0\", className)}>\n {list}\n {allItems.length > 0 && <Pagination {...pager.props} mode={pager.style === \"infinite-scroll\" ? \"load-more\" : pager.props.mode} />}\n </div>\n );\n}\n"]}
|
package/dist-static/tokens.css
CHANGED
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
152
152
|
--ds-nav-h-track-gap: 0px;
|
|
153
153
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
154
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
154
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
155
155
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
156
156
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
157
157
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
160
160
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
161
161
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
162
|
-
--ds-tree-active-bg: var(--ds-
|
|
162
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
163
163
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
164
164
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
165
165
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
185
185
|
--ds-nav-h-track-gap: 0px;
|
|
186
186
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
187
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
187
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
188
188
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
189
189
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
190
190
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
193
193
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
194
194
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
195
|
-
--ds-tree-active-bg: var(--ds-
|
|
195
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
196
196
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
197
197
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
198
198
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
|
@@ -469,7 +469,7 @@
|
|
|
469
469
|
--ds-nav-h-track-border: var(--ds-border-width);
|
|
470
470
|
--ds-nav-h-track-gap: 0px;
|
|
471
471
|
--ds-nav-h-badge-bg: var(--ds-accent-primary);
|
|
472
|
-
--ds-nav-v-active-bg: var(--ds-
|
|
472
|
+
--ds-nav-v-active-bg: var(--ds-accent-subtle);
|
|
473
473
|
--ds-nav-v-active-text: var(--ds-accent-ink);
|
|
474
474
|
--ds-nav-v-active-rail: var(--ds-border-width-thick);
|
|
475
475
|
--ds-nav-v-item-radius: var(--ds-radius-sm);
|
|
@@ -477,7 +477,7 @@
|
|
|
477
477
|
--ds-nav-v-track-padding: var(--ds-space-1);
|
|
478
478
|
--ds-nav-v-active-muted: var(--ds-text-secondary);
|
|
479
479
|
--ds-nav-v-badge-bg: var(--ds-accent-primary);
|
|
480
|
-
--ds-tree-active-bg: var(--ds-
|
|
480
|
+
--ds-tree-active-bg: var(--ds-accent-subtle);
|
|
481
481
|
--ds-tree-active-text: var(--ds-accent-ink);
|
|
482
482
|
--ds-tree-active-muted: var(--ds-text-muted);
|
|
483
483
|
--ds-tree-active-rail: var(--ds-border-width-thick);
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/use-fill-height.ts"],"names":[],"mappings":"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","file":"chunk-DBHVJ7Z3.js","sourcesContent":["import { createContext, useContext, useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * Sprint 25.16 A42 (P31): a page led by a chart, a board or a split view fills the height under its header, and its\n * content scrolls inside it; the page doesn't. SplitView (frame=\"page\"), Gantt and KanbanBoard use this one mechanism.\n *\n * The element takes the rest of the shell's <main> height (main's height less what sits above it and the padding below\n * it) when all of these hold:\n * - it leads the page: above it there is only the page's header, its chrome (notices, tabs, a toolbar, a search or\n * filters row, however tall) and short rows, so a board in a dashboard's last card keeps its own height;\n * - it is the page's last content: nothing after it, up to <main>, takes room, so nothing below it is cut off (the\n * shell's footer is not the page's: it sits below the fold, as it does under a SplitView frame=\"fill\");\n * - its height follows its content: neither its own class nor a box around it gives it one (a fixed height, a flex\n * column that already gives it the rest), and given more, the page grows;\n * - the rest is tall enough to use (a phone on its side keeps the natural height, and the page scrolls).\n * Outside the shell's <main> (AppShell marks it), or inside a view that fills (a Gantt in a SplitView's pane), it keeps\n * its own height. Returns the height in pixels, or null for the natural height.\n */\nexport function useFillHeight(ref: RefObject<HTMLElement | null>, enabled = true): number | null {\n const insideFill = useContext(FillContext);\n const active = enabled && !insideFill;\n const [height, setHeight] = useState<number | null>(null);\n useLayoutEffect(() => {\n const main = ref.current?.closest<HTMLElement>(\"main[data-shell-main]\");\n if (!active || !main || typeof ResizeObserver === \"undefined\") {\n setHeight(null);\n return;\n }\n let frame = 0;\n // the element is read on each measure: a view that changes its layout (stacked or side by side) changes its root\n const measure = () => {\n frame = 0;\n const el = ref.current;\n setHeight(el && main.contains(el) ? fillHeight(el, main) : null);\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n // main's height (the window, a phone's toolbar), and what sits above or after the element at the page's top level (a\n // header's actions wrapping, a banner or a note arriving): the boxes there now, and any that arrive\n const ro = new ResizeObserver(schedule);\n const watch = (box: Element) => {\n ro.observe(box);\n for (const child of Array.from(box.children)) ro.observe(child);\n };\n const page = main.querySelector<HTMLElement>(\"[data-shell-content]\");\n watch(main);\n if (page) watch(page);\n const mo = typeof MutationObserver === \"undefined\" ? null : new MutationObserver((records) => {\n for (const record of records) record.addedNodes.forEach((node) => { if (node instanceof Element) ro.observe(node); });\n schedule();\n });\n mo?.observe(main, { childList: true });\n if (page) mo?.observe(page, { childList: true });\n return () => {\n ro.disconnect();\n mo?.disconnect();\n if (frame) cancelAnimationFrame(frame);\n };\n }, [ref, active]);\n return active ? height : null;\n}\n\n/** Content inside a view that fills: it takes the view's height (h-full), never the page's. */\nexport const FillContext = createContext(false);\n\n/** Below this the rest of the screen is too short to scroll inside (about six rows of a chart). */\nconst MIN_FILL = 240;\n/** A row that may sit between the header and the view: tabs, a toolbar, a filters row (PageContainer's ROW_MAX). */\nconst ROW_MAX = 56;\n\nfunction fillHeight(el: HTMLElement, main: HTMLElement): number | null {\n // the page's own content: the shell's wrapper above its footer, else main\n const page = el.closest<HTMLElement>(\"[data-shell-content]\") ?? main;\n if (!leadsPage(el, page) || !isLastContent(el, page) || keepScroll(el, () => hasOwnHeight(el) || !followsContent(el, main))) return null;\n const mainBox = main.getBoundingClientRect();\n const top = el.getBoundingClientRect().top - mainBox.top - main.clientTop + main.scrollTop;\n const height = Math.floor(main.clientHeight - top - spaceBelow(el, main));\n return height >= MIN_FILL ? height : null;\n}\n\n/**\n * Runs a probe that changes the element's height for a moment, and puts back where everything inside it was scrolled:\n * at its natural height a region that scrolls inside it stops scrolling, and the browser drops its position (Sprint\n * 25.18: the week's hours opened at the working day, then the next measure sent them back to midnight).\n */\nfunction keepScroll<T>(el: HTMLElement, probe: () => T): T {\n const scrolled: Array<[HTMLElement, number, number]> = [];\n for (const node of [el, ...Array.from(el.querySelectorAll<HTMLElement>(\"*\"))]) {\n if (node.scrollTop || node.scrollLeft) scrolled.push([node, node.scrollTop, node.scrollLeft]);\n }\n try {\n return probe();\n } finally {\n for (const [node, top, left] of scrolled) {\n node.scrollTop = top;\n node.scrollLeft = left;\n }\n }\n}\n\n/** Whether a box takes room on the page: an overlay, a portal's anchor, a hidden or an empty node doesn't. */\nfunction takesRoom(box: Element): boolean {\n const style = getComputedStyle(box);\n if (style.display === \"none\" || style.position === \"absolute\" || style.position === \"fixed\") return false;\n const rect = box.getBoundingClientRect();\n return rect.height > 0 && rect.width > 0;\n}\n\n/**\n * The page's chrome, at any height: a notice (an Alert, a banner that wraps to two lines on a phone), tabs, a toolbar, a\n * search or filters row (the review of 1 October: a two-line banner turned the fill off). Content of the page's own (a\n * row of stats, cards, text) is not chrome.\n */\nconst CHROME = '[role=\"alert\"], [role=\"status\"], [role=\"tablist\"], [role=\"toolbar\"], [role=\"search\"]';\nconst isChrome = (box: Element) =>\n box.matches(CHROME) || (box.children.length > 0 && Array.from(box.children).every((child) => !takesRoom(child) || child.matches(CHROME)));\n\n/** Above the element, up to the page's root: only the page's header (its title), its chrome, and rows no taller than ROW_MAX. */\nfunction leadsPage(el: HTMLElement, page: HTMLElement): boolean {\n for (let node: HTMLElement | null = el; node && node !== page; node = node.parentElement) {\n for (let prev = node.previousElementSibling; prev; prev = prev.previousElementSibling) {\n if (!takesRoom(prev)) continue;\n if (prev.matches('[data-gs=\"page-header\"]') || prev.querySelector('[data-gs=\"page-header\"], h1')) continue;\n if (isChrome(prev)) continue;\n if (prev.getBoundingClientRect().height > ROW_MAX) return false;\n }\n }\n return true;\n}\n\n/** Nothing after the element, up to the page's root, takes room. */\nfunction isLastContent(el: HTMLElement, page: HTMLElement): boolean {\n for (let node: HTMLElement | null = el; node && node !== page; node = node.parentElement) {\n for (let next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (takesRoom(next)) return false;\n }\n }\n return true;\n}\n\n/**\n * The element's own CSS gives it a height that isn't its content's: a fixed height of its own (`h-[420px]`), or `h-full`\n * that resolves against a box which already has one. It keeps it. Read with the fill's own height set aside.\n */\nfunction hasOwnHeight(el: HTMLElement): boolean {\n const inline = el.style.height;\n el.style.height = \"\";\n const own = el.offsetHeight;\n el.style.height = \"auto\";\n const natural = el.offsetHeight;\n el.style.height = inline;\n return Math.abs(own - natural) > 1;\n}\n\n/**\n * Given more height, does the page grow? Probed once: the element is made a screen taller and main's top-level box\n * measured. A box of fixed height around it, or a flex column that already gives it its height, absorbs it.\n */\nfunction followsContent(el: HTMLElement, main: HTMLElement): boolean {\n let top: HTMLElement = el;\n while (top.parentElement && top.parentElement !== main) top = top.parentElement;\n const before = top.offsetHeight;\n const inline = el.style.height;\n el.style.height = `${el.offsetHeight + main.clientHeight}px`;\n const grows = top.offsetHeight > before;\n el.style.height = inline;\n return grows;\n}\n\n/** The padding, borders and margins under the element, up to main's own padding: they stay below it. */\nfunction spaceBelow(el: HTMLElement, main: HTMLElement): number {\n const px = (value: string) => parseFloat(value) || 0;\n let space = px(getComputedStyle(main).paddingBottom);\n for (let node: HTMLElement | null = el; node && node !== main; node = node.parentElement) {\n const style = getComputedStyle(node);\n space += px(style.marginBottom);\n if (node !== el) space += px(style.paddingBottom) + px(style.borderBottomWidth);\n }\n return space;\n}\n"]}
|