@galaxy-io/dls 2.8.1 → 2.10.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/README.md +2 -2
- package/dist/beacons/Beacon.d.ts +1 -1
- package/dist/beacons/Beacon.js +12 -28
- package/dist/brand/GalaxyAlchemyWordmark.d.ts +4 -1
- package/dist/brand/GalaxyAlchemyWordmark.js +7 -1
- package/dist/brand/GalaxyFilamentWordmark.d.ts +5 -2
- package/dist/brand/GalaxyFilamentWordmark.js +9 -2
- package/dist/brand/GalaxyLogomark.js +3 -0
- package/dist/brand/PoweredBy.d.ts +27 -0
- package/dist/brand/PoweredBy.js +96 -0
- package/dist/brand/internal/svg/GalaxyAlchemyWordmarkSvg.d.ts +1 -1
- package/dist/brand/internal/svg/GalaxyAlchemyWordmarkSvg.js +34 -8
- package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.d.ts +1 -1
- package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.js +2 -2
- package/dist/charts/Heatmap.js +25 -9
- package/dist/charts/Sparkline.d.ts +1 -1
- package/dist/charts/Sparkline.js +10 -26
- package/dist/charts/chartFormat.d.ts +1 -1
- package/dist/charts/chartFormat.js +2 -2
- package/dist/charts/heatmapGeometry.d.ts +14 -0
- package/dist/charts/heatmapGeometry.js +17 -1
- package/dist/chips/Chip.d.ts +2 -2
- package/dist/chips/Chip.js +15 -31
- package/dist/drawer/Drawer.d.ts +2 -2
- package/dist/drawer/Drawer.js +1 -1
- package/dist/editor/CodeEditor.d.ts +1 -1
- package/dist/editor/CodeEditor.js +2 -1
- package/dist/feedback/Alert.d.ts +36 -9
- package/dist/feedback/Alert.js +26 -8
- package/dist/feedback/ProgressBar.d.ts +4 -1
- package/dist/feedback/ProgressBar.js +17 -30
- package/dist/feedback/ProgressCircle.d.ts +1 -1
- package/dist/feedback/ProgressCircle.js +14 -30
- package/dist/hooks/useEndReached.d.ts +40 -0
- package/dist/hooks/useEndReached.js +69 -0
- package/dist/icons/Icon.d.ts +36 -8
- package/dist/icons/Icon.js +14 -7
- package/dist/inputs/CronInput.js +114 -78
- package/dist/inputs/DateInput.d.ts +1 -1
- package/dist/inputs/DateInput.js +10 -10
- package/dist/inputs/MultiSelectInput.d.ts +3 -1
- package/dist/inputs/MultiSelectInput.js +8 -3
- package/dist/inputs/SelectInput.d.ts +8 -1
- package/dist/inputs/SelectInput.js +52 -25
- package/dist/inputs/internal/selectAll.d.ts +11 -0
- package/dist/inputs/internal/selectAll.js +28 -0
- package/dist/json/JsonViewer.js +7 -6
- package/dist/layout/AppFrame.d.ts +20 -0
- package/dist/layout/AppFrame.js +71 -0
- package/dist/layout/EmptyLayout.d.ts +53 -0
- package/dist/layout/EmptyLayout.js +59 -0
- package/dist/layout/ErrorLayout.d.ts +42 -0
- package/dist/layout/ErrorLayout.js +60 -0
- package/dist/layout/PageLayout.d.ts +26 -0
- package/dist/layout/PageLayout.js +116 -0
- package/dist/layout/PendingLayout.d.ts +30 -0
- package/dist/layout/PendingLayout.js +57 -0
- package/dist/layout/internal/errorState.d.ts +14 -0
- package/dist/layout/internal/errorState.js +49 -0
- package/dist/layout/internal/region.d.ts +10 -0
- package/dist/layout/internal/region.js +24 -0
- package/dist/lists/DescriptionList.js +1 -0
- package/dist/menu/Menu.d.ts +2 -2
- package/dist/menu/Menu.js +6 -13
- package/dist/modal/Modal.d.ts +2 -2
- package/dist/modal/Modal.js +1 -1
- package/dist/navigation/CommandPalette.js +4 -11
- package/dist/navigation/SidebarNav.d.ts +5 -0
- package/dist/navigation/SidebarNav.js +41 -22
- package/dist/navigation/Topbar.js +4 -0
- package/dist/shapes/Circle.d.ts +1 -1
- package/dist/shapes/Circle.js +10 -26
- package/dist/shapes/Square.d.ts +1 -1
- package/dist/shapes/Square.js +10 -26
- package/dist/styles/internal/roleColor.d.ts +3 -0
- package/dist/styles/internal/roleColor.js +42 -0
- package/dist/styles/mixins.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/table/InfiniteSpreadsheet.js +6 -6
- package/dist/table/InfiniteTable.d.ts +57 -18
- package/dist/table/InfiniteTable.js +5 -3
- package/dist/table/TableCore.d.ts +11 -2
- package/dist/table/TableCore.js +108 -87
- package/dist/table/VirtualizedInfiniteTable.d.ts +58 -19
- package/dist/table/VirtualizedInfiniteTable.js +9 -6
- package/dist/table/useInfiniteScrollSentinel.d.ts +13 -13
- package/dist/table/useInfiniteScrollSentinel.js +7 -51
- package/dist/table/useTableColumnLayout.d.ts +8 -2
- package/dist/table/useTableColumnLayout.js +36 -13
- package/dist/theme/tokens/dark.js +1 -1
- package/dist/theme/tokens/light.js +4 -3
- package/dist/theme/tokens/types.d.ts +7 -7
- package/dist/timeline/Timeline.d.ts +1 -1
- package/dist/timeline/Timeline.js +6 -24
- package/dist/tokens.css +1 -1
- package/dist/utils/format.d.ts +35 -10
- package/dist/utils/format.js +60 -12
- package/dist/utils/search.d.ts +15 -0
- package/dist/utils/search.js +24 -0
- package/dist/vite/index.d.ts +16 -2
- package/dist/vite/index.js +28 -19
- package/dist/vite/internal/themeBoot.d.ts +25 -0
- package/dist/vite/internal/themeBoot.js +44 -0
- package/dist/vite/internal/wywOptions.d.ts +46 -0
- package/dist/vite/internal/wywOptions.js +44 -0
- package/package.json +34 -1
|
@@ -16,7 +16,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
16
16
|
* no client-side sorting (the app re-queries when `sort` changes).
|
|
17
17
|
*
|
|
18
18
|
* Built on the shared table core (`TableCore`, `useTableColumnLayout`,
|
|
19
|
-
* `useTableKeyboardNavigation`, `
|
|
19
|
+
* `useTableKeyboardNavigation`, `useEndReached`) plus `useTableVirtualizer`
|
|
20
20
|
* (`@tanstack/react-virtual`, an optional peer). It imports nothing from `InfiniteTable`, so it
|
|
21
21
|
* never needs `@tanstack/react-table`.
|
|
22
22
|
*/
|
|
@@ -53,7 +53,7 @@ function sortAnnouncement(sort, columns) {
|
|
|
53
53
|
}
|
|
54
54
|
/** InfiniteTable with a virtual body, for tens of thousands of rows. */
|
|
55
55
|
var VirtualizedInfiniteTableInner = forwardRef(function VirtualizedInfiniteTable(props, ref) {
|
|
56
|
-
const { columns, totalRowCount, getRowData, getRowId, size: sizeProp, isLoading: isLoadingProp, error: errorProp, emptyState, onEndReached, onRowClick, activeRowId, rowActions, sort, defaultSort, onSortChange, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns: canResizeColumnsProp, canCustomizeColumns: canCustomizeColumnsProp, ariaLabel, id, className, style, ...rest } = props;
|
|
56
|
+
const { columns, totalRowCount, getRowData, getRowId, size: sizeProp, isLoading: isLoadingProp, error: errorProp, emptyState, onEndReached, onRowClick, activeRowId, rowActions, sort, defaultSort, onSortChange, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns: canResizeColumnsProp, canCustomizeColumns: canCustomizeColumnsProp, hasHeader = true, inset: insetProp, ariaLabel, id, className, style, ...rest } = props;
|
|
57
57
|
const error = errorProp === "" ? void 0 : errorProp;
|
|
58
58
|
const size = sizeProp ?? "MEDIUM";
|
|
59
59
|
const isLoading = isLoadingProp ?? false;
|
|
@@ -95,7 +95,8 @@ var VirtualizedInfiniteTableInner = forwardRef(function VirtualizedInfiniteTable
|
|
|
95
95
|
canCustomizeColumns,
|
|
96
96
|
leadingCount: 0,
|
|
97
97
|
hasTrailing: hasTrailingColumn,
|
|
98
|
-
syntheticWidthPx: metrics.rowHeightPx
|
|
98
|
+
syntheticWidthPx: metrics.rowHeightPx,
|
|
99
|
+
insetPx: insetProp ?? 0
|
|
99
100
|
});
|
|
100
101
|
const visibleColumns = layout.visibleColumns;
|
|
101
102
|
const hasFooter = visibleColumns.some(({ column }) => column.footer !== void 0 && column.footer !== null);
|
|
@@ -133,13 +134,14 @@ var VirtualizedInfiniteTableInner = forwardRef(function VirtualizedInfiniteTable
|
|
|
133
134
|
}
|
|
134
135
|
}, []);
|
|
135
136
|
const virtualizerRef = useRef(null);
|
|
137
|
+
const headerHeightPx = hasHeader ? metrics.headerHeightPx : 0;
|
|
136
138
|
const navigation = useTableKeyboardNavigation({
|
|
137
139
|
rowCount,
|
|
138
140
|
getPageSize: useCallback(() => {
|
|
139
141
|
const scroll = scrollRef.current;
|
|
140
142
|
if (scroll === null) return 1;
|
|
141
|
-
return Math.max(1, Math.floor((scroll.clientHeight -
|
|
142
|
-
}, [metrics.rowHeightPx,
|
|
143
|
+
return Math.max(1, Math.floor((scroll.clientHeight - headerHeightPx) / metrics.rowHeightPx) - 1);
|
|
144
|
+
}, [metrics.rowHeightPx, headerHeightPx]),
|
|
143
145
|
scrollToIndex: (index) => virtualizerRef.current?.scrollToIndex(index),
|
|
144
146
|
onKeyDown: handleKey
|
|
145
147
|
});
|
|
@@ -151,7 +153,7 @@ var VirtualizedInfiniteTableInner = forwardRef(function VirtualizedInfiniteTable
|
|
|
151
153
|
count: rowCount,
|
|
152
154
|
scrollRef,
|
|
153
155
|
rowHeightPx: metrics.rowHeightPx,
|
|
154
|
-
headerHeightPx
|
|
156
|
+
headerHeightPx,
|
|
155
157
|
footerHeightPx: hasFooter ? metrics.headerHeightPx : 0,
|
|
156
158
|
getItemKey,
|
|
157
159
|
keepIndexes: rowCount > 0 ? [navigation.tabStopIndex] : []
|
|
@@ -209,6 +211,7 @@ var VirtualizedInfiniteTableInner = forwardRef(function VirtualizedInfiniteTable
|
|
|
209
211
|
const scrollMargin = virtualizer.options.scrollMargin;
|
|
210
212
|
return /* @__PURE__ */ jsx(TableFrame, {
|
|
211
213
|
metrics,
|
|
214
|
+
hasHeader,
|
|
212
215
|
columnLayout: layout,
|
|
213
216
|
leadingHeaders: [],
|
|
214
217
|
trailingHeader: canCustomizeColumns ? /* @__PURE__ */ jsx(TableColumnsMenu, {
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @internal
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* passive `scroll` listener. Nothing runs at module scope.
|
|
2
|
+
* @internal
|
|
3
|
+
* @deprecated Use `@galaxy-io/dls/hooks/useEndReached`, which this wraps (the same observer, with
|
|
4
|
+
* `rowCount` named `itemCount` and `scrollRef` and `marginPx` optional). Kept so the published
|
|
5
|
+
* subpath keeps working; it goes in 3.0.
|
|
6
|
+
*/
|
|
7
|
+
import type { RefObject } from "react";
|
|
8
|
+
/**
|
|
9
|
+
* @internal Options for `useInfiniteScrollSentinel`.
|
|
10
|
+
* @deprecated Use `UseEndReachedOptions` from `@galaxy-io/dls/hooks/useEndReached`.
|
|
12
11
|
*/
|
|
13
|
-
import { type RefObject } from "react";
|
|
14
|
-
/** @internal Options for `useInfiniteScrollSentinel`. */
|
|
15
12
|
export interface UseInfiniteScrollSentinelOptions {
|
|
16
13
|
/** The table's scroll container. */
|
|
17
14
|
scrollRef: RefObject<HTMLElement | null>;
|
|
@@ -24,5 +21,8 @@ export interface UseInfiniteScrollSentinelOptions {
|
|
|
24
21
|
/** How far below the visible area the end counts as reached, in pixels. */
|
|
25
22
|
marginPx: number;
|
|
26
23
|
}
|
|
27
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* @internal Observes the zero-size sentinel and calls `onEndReached`; returns the sentinel's ref.
|
|
26
|
+
* @deprecated Use `useEndReached` from `@galaxy-io/dls/hooks/useEndReached`.
|
|
27
|
+
*/
|
|
28
28
|
export declare function useInfiniteScrollSentinel({ scrollRef, onEndReached, isEnabled, rowCount, marginPx, }: UseInfiniteScrollSentinelOptions): RefObject<HTMLDivElement | null>;
|
|
@@ -1,61 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEndReached } from "../hooks/useEndReached.js";
|
|
2
2
|
//#region src/table/useInfiniteScrollSentinel.ts
|
|
3
3
|
/**
|
|
4
|
-
* @internal
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The `onEndReached` sentinel: a 1px element after the table, observed with an
|
|
8
|
-
* `IntersectionObserver` whose bottom margin is `marginPx` (`TABLE_END_REACHED_MARGIN_PX`). The root is the
|
|
9
|
-
* scroll container when it overflows, otherwise the viewport, so a table in an unbounded parent
|
|
10
|
-
* pages on page scroll. Armed only while enabled (not loading, no error), re-armed when the row
|
|
11
|
-
* count changes, and calls `onEndReached` at most once per row count: an app with no next page
|
|
12
|
-
* adds no rows, so it is not called again. Without `IntersectionObserver` it falls back to a
|
|
13
|
-
* passive `scroll` listener. Nothing runs at module scope.
|
|
4
|
+
* @internal Observes the zero-size sentinel and calls `onEndReached`; returns the sentinel's ref.
|
|
5
|
+
* @deprecated Use `useEndReached` from `@galaxy-io/dls/hooks/useEndReached`.
|
|
14
6
|
*/
|
|
15
|
-
/** @internal Observes the sentinel and calls `onEndReached`; returns the sentinel's ref. */
|
|
16
7
|
function useInfiniteScrollSentinel({ scrollRef, onEndReached, isEnabled, rowCount, marginPx }) {
|
|
17
|
-
|
|
18
|
-
const onEndReachedRef = useRef(onEndReached);
|
|
19
|
-
onEndReachedRef.current = onEndReached;
|
|
20
|
-
const calledForCountRef = useRef(null);
|
|
21
|
-
const hasHandler = onEndReached !== void 0;
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
const scroll = scrollRef.current;
|
|
24
|
-
const sentinel = sentinelRef.current;
|
|
25
|
-
if (!hasHandler || !isEnabled || scroll === null || sentinel === null) return;
|
|
26
|
-
if (calledForCountRef.current === rowCount) return;
|
|
27
|
-
const reach = () => {
|
|
28
|
-
if (calledForCountRef.current === rowCount) return;
|
|
29
|
-
calledForCountRef.current = rowCount;
|
|
30
|
-
onEndReachedRef.current?.();
|
|
31
|
-
};
|
|
32
|
-
const isScrollRoot = scroll.scrollHeight > scroll.clientHeight;
|
|
33
|
-
if (typeof IntersectionObserver === "undefined") {
|
|
34
|
-
const target = isScrollRoot ? scroll : window;
|
|
35
|
-
const check = () => {
|
|
36
|
-
const bottom = isScrollRoot ? scroll.getBoundingClientRect().bottom : window.innerHeight;
|
|
37
|
-
if (sentinel.getBoundingClientRect().top - bottom < marginPx) reach();
|
|
38
|
-
};
|
|
39
|
-
check();
|
|
40
|
-
target.addEventListener("scroll", check, { passive: true });
|
|
41
|
-
return () => target.removeEventListener("scroll", check);
|
|
42
|
-
}
|
|
43
|
-
const observer = new IntersectionObserver((entries) => {
|
|
44
|
-
if (entries.some((entry) => entry.isIntersecting)) reach();
|
|
45
|
-
}, {
|
|
46
|
-
root: isScrollRoot ? scroll : null,
|
|
47
|
-
rootMargin: `0px 0px ${marginPx}px 0px`
|
|
48
|
-
});
|
|
49
|
-
observer.observe(sentinel);
|
|
50
|
-
return () => observer.disconnect();
|
|
51
|
-
}, [
|
|
8
|
+
return useEndReached({
|
|
52
9
|
scrollRef,
|
|
53
|
-
|
|
10
|
+
onEndReached,
|
|
54
11
|
isEnabled,
|
|
55
|
-
rowCount,
|
|
12
|
+
itemCount: rowCount,
|
|
56
13
|
marginPx
|
|
57
|
-
|
|
58
|
-
return sentinelRef;
|
|
14
|
+
});
|
|
59
15
|
}
|
|
60
16
|
//#endregion
|
|
61
17
|
export { useInfiniteScrollSentinel };
|
|
@@ -63,6 +63,12 @@ export interface UseTableColumnLayoutOptions<TData> {
|
|
|
63
63
|
hasTrailing: boolean;
|
|
64
64
|
/** Width of a synthetic column, in pixels (the row height). */
|
|
65
65
|
syntheticWidthPx: number;
|
|
66
|
+
/**
|
|
67
|
+
* The table's `inset`, in pixels: added to the first and last cell of every row (padding and
|
|
68
|
+
* width), so the content moves in while rows, fills and hairlines keep the full width.
|
|
69
|
+
* @default 0
|
|
70
|
+
*/
|
|
71
|
+
insetPx?: number;
|
|
66
72
|
}
|
|
67
73
|
/** @internal What `useTableColumnLayout` returns. */
|
|
68
74
|
export interface TableColumnLayoutResult<TData> {
|
|
@@ -72,7 +78,7 @@ export interface TableColumnLayoutResult<TData> {
|
|
|
72
78
|
visibleColumns: TableResolvedColumn<TData>[];
|
|
73
79
|
/** Every column in display order with its visibility, for the Columns menu. */
|
|
74
80
|
menuEntries: TableColumnsMenuEntry[];
|
|
75
|
-
/** Custom properties for the table root: per-column flex, min, max and pinned offset,
|
|
81
|
+
/** Custom properties for the table root: per-column flex, min, max and pinned offset, the table min width and `--gx-table-inset`. */
|
|
76
82
|
variables: Record<`--gx-${string}`, string>;
|
|
77
83
|
/** Width of a resizable column for the resize handle: its resolved or measured width. */
|
|
78
84
|
getColumnWidth: (id: string) => number;
|
|
@@ -90,4 +96,4 @@ export interface TableColumnLayoutResult<TData> {
|
|
|
90
96
|
resetLayout: () => void;
|
|
91
97
|
}
|
|
92
98
|
/** Column arrangement state and the column custom properties. */
|
|
93
|
-
export declare function useTableColumnLayout<TData>({ columns, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns, canCustomizeColumns, leadingCount, hasTrailing, syntheticWidthPx, }: UseTableColumnLayoutOptions<TData>): TableColumnLayoutResult<TData>;
|
|
99
|
+
export declare function useTableColumnLayout<TData>({ columns, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns, canCustomizeColumns, leadingCount, hasTrailing, syntheticWidthPx, insetPx, }: UseTableColumnLayoutOptions<TData>): TableColumnLayoutResult<TData>;
|
|
@@ -33,7 +33,7 @@ function pinGroup(pin) {
|
|
|
33
33
|
return 1;
|
|
34
34
|
}
|
|
35
35
|
/** Column arrangement state and the column custom properties. */
|
|
36
|
-
function useTableColumnLayout({ columns, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns, canCustomizeColumns, leadingCount, hasTrailing, syntheticWidthPx }) {
|
|
36
|
+
function useTableColumnLayout({ columns, columnLayout, defaultColumnLayout, onColumnLayoutChange, canResizeColumns, canCustomizeColumns, leadingCount, hasTrailing, syntheticWidthPx, insetPx = 0 }) {
|
|
37
37
|
const [layout, setLayout] = useControlledState({
|
|
38
38
|
value: columnLayout,
|
|
39
39
|
defaultValue: defaultColumnLayout,
|
|
@@ -100,44 +100,55 @@ function useTableColumnLayout({ columns, columnLayout, defaultColumnLayout, onCo
|
|
|
100
100
|
console.warn(`[@galaxy-io/dls] Table column "${column.id}" is pinned without a \`width\`; it falls back to 150px.`);
|
|
101
101
|
}
|
|
102
102
|
}, [visibleColumns]);
|
|
103
|
+
/** The inset a column's cells carry: `insetPx` at each end of the row it sits on. */
|
|
104
|
+
const edgeInsetFor = useCallback((position) => ((leadingCount === 0 && position === 0 ? 1 : 0) + (!hasTrailing && position === visibleColumns.length - 1 ? 1 : 0)) * insetPx, [
|
|
105
|
+
leadingCount,
|
|
106
|
+
hasTrailing,
|
|
107
|
+
visibleColumns.length,
|
|
108
|
+
insetPx
|
|
109
|
+
]);
|
|
103
110
|
const variables = useMemo(() => {
|
|
104
111
|
const result = {};
|
|
105
|
-
let minTotal = (leadingCount + (hasTrailing ? 1 : 0)) * syntheticWidthPx;
|
|
106
|
-
let leftOffset = leadingCount * syntheticWidthPx;
|
|
112
|
+
let minTotal = (leadingCount + (hasTrailing ? 1 : 0)) * syntheticWidthPx + 2 * insetPx;
|
|
113
|
+
let leftOffset = leadingCount * syntheticWidthPx + (leadingCount > 0 ? insetPx : 0);
|
|
107
114
|
const rightColumns = [];
|
|
108
115
|
for (const resolved of visibleColumns) {
|
|
109
116
|
const { column, position, minWidth, pin } = resolved;
|
|
110
117
|
const width = resolvedWidths.get(column.id);
|
|
118
|
+
const edge = edgeInsetFor(position);
|
|
111
119
|
const prefix = `--gx-table-col-${position}`;
|
|
112
120
|
if (width !== void 0) {
|
|
113
|
-
result[`${prefix}-flex`] = `0 0 ${width}px`;
|
|
114
|
-
result[`${prefix}-min`] = `${width}px`;
|
|
115
|
-
result[`${prefix}-max`] = `${width}px`;
|
|
121
|
+
result[`${prefix}-flex`] = `0 0 ${width + edge}px`;
|
|
122
|
+
result[`${prefix}-min`] = `${width + edge}px`;
|
|
123
|
+
result[`${prefix}-max`] = `${width + edge}px`;
|
|
116
124
|
minTotal += width;
|
|
117
125
|
} else {
|
|
118
|
-
result[`${prefix}-flex`] =
|
|
119
|
-
result[`${prefix}-min`] = `${minWidth}px`;
|
|
126
|
+
result[`${prefix}-flex`] = `1 1 ${edge}px`;
|
|
127
|
+
result[`${prefix}-min`] = `${minWidth + edge}px`;
|
|
120
128
|
result[`${prefix}-max`] = "none";
|
|
121
129
|
minTotal += minWidth;
|
|
122
130
|
}
|
|
123
131
|
if (pin === Side.LEFT) {
|
|
124
132
|
result[`${prefix}-offset`] = `${leftOffset}px`;
|
|
125
|
-
leftOffset += width ?? 150;
|
|
133
|
+
leftOffset += (width ?? 150) + edge;
|
|
126
134
|
} else if (pin === Side.RIGHT) rightColumns.push(resolved);
|
|
127
135
|
}
|
|
128
|
-
let rightOffset = hasTrailing ? syntheticWidthPx : 0;
|
|
136
|
+
let rightOffset = hasTrailing ? syntheticWidthPx + insetPx : 0;
|
|
129
137
|
for (const { column, position } of [...rightColumns].reverse()) {
|
|
130
138
|
result[`--gx-table-col-${position}-offset`] = `${rightOffset}px`;
|
|
131
|
-
rightOffset += resolvedWidths.get(column.id) ?? 150;
|
|
139
|
+
rightOffset += (resolvedWidths.get(column.id) ?? 150) + edgeInsetFor(position);
|
|
132
140
|
}
|
|
133
141
|
result["--gx-table-min-width"] = `${minTotal}px`;
|
|
142
|
+
if (insetPx > 0) result["--gx-table-inset"] = `${insetPx}px`;
|
|
134
143
|
return result;
|
|
135
144
|
}, [
|
|
136
145
|
visibleColumns,
|
|
137
146
|
resolvedWidths,
|
|
138
147
|
leadingCount,
|
|
139
148
|
hasTrailing,
|
|
140
|
-
syntheticWidthPx
|
|
149
|
+
syntheticWidthPx,
|
|
150
|
+
insetPx,
|
|
151
|
+
edgeInsetFor
|
|
141
152
|
]);
|
|
142
153
|
const menuEntries = useMemo(() => {
|
|
143
154
|
const hidden = new Set(hiddenKey === "" ? [] : hiddenKey.split("\0"));
|
|
@@ -190,7 +201,19 @@ function useTableColumnLayout({ columns, columnLayout, defaultColumnLayout, onCo
|
|
|
190
201
|
observerRef.current.observe(element);
|
|
191
202
|
}, [measure]);
|
|
192
203
|
useEffect(() => () => observerRef.current?.disconnect(), []);
|
|
193
|
-
const getColumnWidth = useCallback((id) =>
|
|
204
|
+
const getColumnWidth = useCallback((id) => {
|
|
205
|
+
const resolved = resolvedWidths.get(id);
|
|
206
|
+
if (resolved !== void 0) return resolved;
|
|
207
|
+
const width = measured[id];
|
|
208
|
+
if (width === void 0) return 60;
|
|
209
|
+
const position = visibleColumns.findIndex(({ column }) => column.id === id);
|
|
210
|
+
return position === -1 ? width : width - edgeInsetFor(position);
|
|
211
|
+
}, [
|
|
212
|
+
resolvedWidths,
|
|
213
|
+
measured,
|
|
214
|
+
visibleColumns,
|
|
215
|
+
edgeInsetFor
|
|
216
|
+
]);
|
|
194
217
|
const resizeColumn = useCallback((id, width) => {
|
|
195
218
|
const current = layoutRef.current;
|
|
196
219
|
setLayout({
|
|
@@ -3,7 +3,7 @@ import { TYPE_SCALE } from "./scales.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Dark theme, resolved hex. Everything is Galaxy monochrome: `solid.primary` is `text.primary`
|
|
5
5
|
* with `background.base` on it, `background.selected` is `text.primary` at 12% over
|
|
6
|
-
* `background.base
|
|
6
|
+
* `background.base` (Light uses 10%).
|
|
7
7
|
*
|
|
8
8
|
* Families (`<family>` below is any of the 17; the palette steps are `PALETTE`):
|
|
9
9
|
* - `text`: brighter and more vivid than Tailwind's 400: OKLCH lightness ~0.03 above it, at the
|
|
@@ -2,8 +2,9 @@ import { TYPE_SCALE } from "./scales.js";
|
|
|
2
2
|
//#region src/theme/tokens/light.ts
|
|
3
3
|
/**
|
|
4
4
|
* Light theme, resolved hex. Everything is Galaxy monochrome: `solid.primary` is `text.primary`
|
|
5
|
-
* with `background.base` on it, `background.selected` is `text.primary` at
|
|
6
|
-
* `background.base
|
|
5
|
+
* with `background.base` on it, `background.selected` is `text.primary` at 10% over
|
|
6
|
+
* `background.base` (Dark uses 12%: a lift off near-black reads quieter than a darkening of white,
|
|
7
|
+
* and at 12% Light's selected row jumped well past `pressed`).
|
|
7
8
|
*
|
|
8
9
|
* Families (`<family>` below is any of the 17; the palette steps are `PALETTE`):
|
|
9
10
|
* - `text`: the lightest OKLCH lightness, at the largest in-gamut chroma for the hue, that reaches
|
|
@@ -37,7 +38,7 @@ var LIGHT_THEME = {
|
|
|
37
38
|
tertiary: "#efeff0",
|
|
38
39
|
hovered: "#f5f5f5",
|
|
39
40
|
pressed: "#eeeeee",
|
|
40
|
-
selected: "#
|
|
41
|
+
selected: "#e7e7e7",
|
|
41
42
|
disabled: "#f3f3f4",
|
|
42
43
|
success: "#ecfcf0",
|
|
43
44
|
warning: "#fff8eb",
|
|
@@ -42,7 +42,7 @@ export type SolidColor = {
|
|
|
42
42
|
/** The fill while pressed. */
|
|
43
43
|
pressed: string;
|
|
44
44
|
};
|
|
45
|
-
/** Type-scale steps (
|
|
45
|
+
/** Type-scale steps (AGENTS.md "Type scale"). */
|
|
46
46
|
export type TypeStep = "caption" | "body_sm" | "body_md" | "body_lg" | "heading_sm" | "heading_md" | "heading_lg" | "display_sm" | "display_lg";
|
|
47
47
|
/** Serif (Cardo) is editorial only: it has no `caption`, `body_sm` or `body_md` step. */
|
|
48
48
|
type SerifStep = Exclude<TypeStep, "caption" | "body_sm" | "body_md">;
|
|
@@ -50,7 +50,7 @@ type SerifStep = Exclude<TypeStep, "caption" | "body_sm" | "body_md">;
|
|
|
50
50
|
export type FontScale<S extends TypeStep = TypeStep> = {
|
|
51
51
|
/** CSS `font-family` stack. */
|
|
52
52
|
family: string;
|
|
53
|
-
/** The only two weights (
|
|
53
|
+
/** The only two weights (AGENTS.md "Type"). */
|
|
54
54
|
weight: {
|
|
55
55
|
regular: number;
|
|
56
56
|
medium: number;
|
|
@@ -82,7 +82,7 @@ export type Theme = {
|
|
|
82
82
|
hovered: string;
|
|
83
83
|
/** A neutral row or control while pressed. */
|
|
84
84
|
pressed: string;
|
|
85
|
-
/** The chosen item (menus, trees, tabs, nav, tables): `text.primary`
|
|
85
|
+
/** The chosen item (menus, trees, tabs, nav, tables): `text.primary` over `base`, 12% in Dark and 10% in Light. */
|
|
86
86
|
selected: string;
|
|
87
87
|
/** Disabled controls. */
|
|
88
88
|
disabled: string;
|
|
@@ -161,16 +161,16 @@ export type Theme = {
|
|
|
161
161
|
};
|
|
162
162
|
/** Theme-independent scales, emitted once on `:root`. */
|
|
163
163
|
export type Scales = {
|
|
164
|
-
/** Gap and padding (
|
|
164
|
+
/** Gap and padding (AGENTS.md "Spacing"). */
|
|
165
165
|
space: Record<Space, string>;
|
|
166
|
-
/** Corner radii (
|
|
166
|
+
/** Corner radii (AGENTS.md "Radius"). */
|
|
167
167
|
radius: {
|
|
168
168
|
sm: string;
|
|
169
169
|
md: string;
|
|
170
170
|
lg: string;
|
|
171
171
|
pill: string;
|
|
172
172
|
};
|
|
173
|
-
/** Transition durations (
|
|
173
|
+
/** Transition durations (AGENTS.md "Motion"). */
|
|
174
174
|
duration: {
|
|
175
175
|
fast: string;
|
|
176
176
|
base: string;
|
|
@@ -183,7 +183,7 @@ export type Scales = {
|
|
|
183
183
|
toast: number;
|
|
184
184
|
tooltip: number;
|
|
185
185
|
};
|
|
186
|
-
/** Control heights: the canonical size rungs (
|
|
186
|
+
/** Control heights: the canonical size rungs (AGENTS.md "Control rungs"). */
|
|
187
187
|
size: {
|
|
188
188
|
control: {
|
|
189
189
|
xSmall: string;
|
|
@@ -19,7 +19,7 @@ export declare enum TimelineMarkerShape {
|
|
|
19
19
|
/** No box: the dot or icon sits on the rail, 4px clear of the line above and below it. */
|
|
20
20
|
NONE = "NONE"
|
|
21
21
|
}
|
|
22
|
-
/** Marker color of one item (
|
|
22
|
+
/** Marker color of one item (AGENTS.md "Variant": color set). */
|
|
23
23
|
export declare enum TimelineVariant {
|
|
24
24
|
/** `text.primary` marker in a `border.primary` box. */
|
|
25
25
|
PRIMARY = "PRIMARY",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Text, { TextSize, TextVariant } from "../text/Text.js";
|
|
2
|
+
import { ROLE_COLOR_TO_CSS_MAP } from "../styles/internal/roleColor.js";
|
|
2
3
|
import Beacon, { BeaconSize, BeaconVariant } from "../beacons/Beacon.js";
|
|
3
4
|
import Icon, { IconVariant } from "../icons/Icon.js";
|
|
4
5
|
/* empty css */
|
|
@@ -41,7 +42,7 @@ var TimelineMarkerShape = /* @__PURE__ */ function(TimelineMarkerShape) {
|
|
|
41
42
|
TimelineMarkerShape["NONE"] = "NONE";
|
|
42
43
|
return TimelineMarkerShape;
|
|
43
44
|
}({});
|
|
44
|
-
/** Marker color of one item (
|
|
45
|
+
/** Marker color of one item (AGENTS.md "Variant": color set). */
|
|
45
46
|
var TimelineVariant = /* @__PURE__ */ function(TimelineVariant) {
|
|
46
47
|
/** `text.primary` marker in a `border.primary` box. */
|
|
47
48
|
TimelineVariant["PRIMARY"] = "PRIMARY";
|
|
@@ -211,29 +212,10 @@ var TIMELINE_VARIANT_TO_CSS_MAP = {
|
|
|
211
212
|
/**
|
|
212
213
|
* Categorical `color` on the marker: `text.<family>`, which an icon marker (`IconVariant.INHERIT`)
|
|
213
214
|
* takes, and `border.<family>` and the `background.<family>` fill on the box.
|
|
215
|
+
* Reads the shared `--gx-role-*` variables that `ROLE_COLOR_TO_CSS_MAP` sets per family, so the
|
|
216
|
+
* twenty families are written once (`styles/internal/roleColor`).
|
|
214
217
|
*/
|
|
215
|
-
var
|
|
216
|
-
success: "gx-Timeline-success-s1khc5e9",
|
|
217
|
-
warning: "gx-Timeline-warning-wob0jun",
|
|
218
|
-
error: "gx-Timeline-error-ecpz10x",
|
|
219
|
-
red: "gx-Timeline-red-r1arc1uv",
|
|
220
|
-
orange: "gx-Timeline-orange-o1x7dvj6",
|
|
221
|
-
amber: "gx-Timeline-amber-a1fx1m3c",
|
|
222
|
-
yellow: "gx-Timeline-yellow-y1gy5gqm",
|
|
223
|
-
lime: "gx-Timeline-lime-ltyv4re",
|
|
224
|
-
green: "gx-Timeline-green-g1506u15",
|
|
225
|
-
emerald: "gx-Timeline-emerald-e2f8n55",
|
|
226
|
-
teal: "gx-Timeline-teal-t1bza0tc",
|
|
227
|
-
cyan: "gx-Timeline-cyan-c1vbt6lr",
|
|
228
|
-
sky: "gx-Timeline-sky-sjtm0e",
|
|
229
|
-
blue: "gx-Timeline-blue-bek3kdh",
|
|
230
|
-
indigo: "gx-Timeline-indigo-i13hn3pe",
|
|
231
|
-
violet: "gx-Timeline-violet-vdf3rdi",
|
|
232
|
-
purple: "gx-Timeline-purple-pjv99mk",
|
|
233
|
-
fuchsia: "gx-Timeline-fuchsia-f4wvpbo",
|
|
234
|
-
pink: "gx-Timeline-pink-p1qqjpue",
|
|
235
|
-
rose: "gx-Timeline-rose-r183jhdd"
|
|
236
|
-
};
|
|
218
|
+
var TIMELINE_COLOR_CSS = "gx-Timeline-TIMELINE_COLOR_CSS-t1khc5e9";
|
|
237
219
|
/** A vertical list of events with dot or icon markers (boxed or bare) on a hairline rail. */
|
|
238
220
|
var Timeline = forwardRef(function Timeline({ items, size = "MEDIUM", markerShape = "SQUARE", isFilled = false, className, style, ...rest }, ref) {
|
|
239
221
|
const textSize = TIMELINE_SIZE_TO_TEXT_SIZE_MAP[size];
|
|
@@ -252,7 +234,7 @@ var Timeline = forwardRef(function Timeline({ items, size = "MEDIUM", markerShap
|
|
|
252
234
|
children: [/* @__PURE__ */ jsxs(Rail, {
|
|
253
235
|
"aria-hidden": true,
|
|
254
236
|
children: [/* @__PURE__ */ jsx(Marker, {
|
|
255
|
-
className: cx(color !== void 0 ?
|
|
237
|
+
className: cx(color !== void 0 ? cx(ROLE_COLOR_TO_CSS_MAP[color], TIMELINE_COLOR_CSS) : TIMELINE_VARIANT_TO_CSS_MAP[variant], TIMELINE_MARKER_SHAPE_TO_CSS_MAP[markerShape], isFilled && markerShape !== "NONE" && FILLED_CSS),
|
|
256
238
|
children: item.icon === void 0 ? /* @__PURE__ */ jsx(Beacon, {
|
|
257
239
|
size: TIMELINE_SIZE_TO_BEACON_SIZE_MAP[size],
|
|
258
240
|
...color !== void 0 ? { color } : { variant: TIMELINE_VARIANT_TO_BEACON_VARIANT_MAP[variant] },
|
package/dist/tokens.css
CHANGED
|
@@ -410,7 +410,7 @@
|
|
|
410
410
|
--gx-color-background-tertiary: #efeff0;
|
|
411
411
|
--gx-color-background-hovered: #f5f5f5;
|
|
412
412
|
--gx-color-background-pressed: #eeeeee;
|
|
413
|
-
--gx-color-background-selected: #
|
|
413
|
+
--gx-color-background-selected: #e7e7e7;
|
|
414
414
|
--gx-color-background-disabled: #f3f3f4;
|
|
415
415
|
--gx-color-background-success: #ecfcf0;
|
|
416
416
|
--gx-color-background-warning: #fff8eb;
|
package/dist/utils/format.d.ts
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Display formatting for numbers, byte sizes, durations, relative times and percentages
|
|
3
|
-
* (
|
|
4
|
-
* under SSR. Number parts default to the `en-US` locale (not the runtime's) so
|
|
5
|
-
* render the same string.
|
|
2
|
+
* Display formatting for numbers, byte sizes, durations, relative times, dates and percentages
|
|
3
|
+
* (`docs/components.md`, Hooks and utils). Pure functions on `Intl`, no dependencies, safe at
|
|
4
|
+
* module scope and under SSR. Number parts default to the `en-US` locale (not the runtime's) so
|
|
5
|
+
* server and client render the same string.
|
|
6
6
|
*
|
|
7
7
|
* `precision` is always the maximum number of fraction digits; trailing zeros are dropped
|
|
8
8
|
* (`formatPercent(0.5)` → `"50%"`, not `"50.0%"`). Non-finite input (`NaN`, `±Infinity`) is
|
|
9
9
|
* returned as `formatNumber` prints it (`"NaN"`, `"∞"`, `"-∞"`).
|
|
10
|
+
*
|
|
11
|
+
* Every formatter also takes a `bigint` (a database count, a unix-millisecond timestamp), so call
|
|
12
|
+
* sites never wrap one in `Number()`. `formatNumber` prints a bigint exactly (`Intl` formats it
|
|
13
|
+
* natively); compact numbers, byte sizes, durations and relative times scale and round anyway, so
|
|
14
|
+
* they convert it to a number first (exact up to 2^53).
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* What a missing value prints as: an em dash, in a table cell, a description list or a chart
|
|
18
|
+
* tooltip. One constant so every "no value" in an app reads the same. Render it in
|
|
19
|
+
* `TextVariant.TERTIARY`.
|
|
10
20
|
*/
|
|
21
|
+
export declare const EMPTY_VALUE = "\u2014";
|
|
11
22
|
/**
|
|
12
23
|
* Formats a number with grouping. `1234` → `"1,234"`; `{ compact: true }` → `"1.2k"`
|
|
13
24
|
* (suffixes `k M B T`). `precision` is the maximum fraction digits (default `1` when compact,
|
|
14
|
-
* otherwise the `Intl` default of `3`). `locale` defaults to `"en-US"`.
|
|
25
|
+
* otherwise the `Intl` default of `3`). `locale` defaults to `"en-US"`. A `bigint` prints exactly
|
|
26
|
+
* (`12345678901234567890n` → `"12,345,678,901,234,567,890"`).
|
|
15
27
|
*/
|
|
16
|
-
export declare function formatNumber(
|
|
28
|
+
export declare function formatNumber(input: number | bigint, opts?: {
|
|
17
29
|
compact?: boolean;
|
|
18
30
|
precision?: number;
|
|
19
31
|
locale?: string;
|
|
@@ -23,7 +35,7 @@ export declare function formatNumber(n: number, opts?: {
|
|
|
23
35
|
* `{ binary: true }` uses IEC units (`KiB`, base 1024). Whole bytes have no fraction digits.
|
|
24
36
|
* `precision` is the maximum fraction digits (default `1`).
|
|
25
37
|
*/
|
|
26
|
-
export declare function formatBytes(
|
|
38
|
+
export declare function formatBytes(input: number | bigint, opts?: {
|
|
27
39
|
precision?: number;
|
|
28
40
|
binary?: boolean;
|
|
29
41
|
}): string;
|
|
@@ -34,21 +46,34 @@ export declare function formatBytes(bytes: number, opts?: {
|
|
|
34
46
|
* finite); zero units are omitted and the
|
|
35
47
|
* remainder is truncated. Zero is `"0s"` / `"0 seconds"`. `style` defaults to `"compact"`.
|
|
36
48
|
*/
|
|
37
|
-
export declare function formatDuration(
|
|
49
|
+
export declare function formatDuration(input: number | bigint, opts?: {
|
|
38
50
|
style?: "compact" | "long";
|
|
39
51
|
maxUnits?: number;
|
|
40
52
|
}): string;
|
|
41
53
|
/**
|
|
42
|
-
* Formats a date
|
|
54
|
+
* Formats a date (or a unix-millisecond timestamp, `number` or `bigint`) relative to `now`
|
|
55
|
+
* (default: the current time, read at call time).
|
|
43
56
|
* `{ style: "short" }` (default) → `"3m ago"`, `"in 2d"`, `"now"` (units `s m h d w mo y`);
|
|
44
57
|
* `{ style: "long" }` → `Intl.RelativeTimeFormat` with `numeric: "auto"` (`"3 minutes ago"`,
|
|
45
58
|
* `"in 2 days"`, `"yesterday"`, `"now"`). Uses the largest unit that fits, truncated;
|
|
46
59
|
* months are 30 days, years 365 days. Under 1 second is `"now"`.
|
|
47
60
|
*/
|
|
48
|
-
export declare function formatRelativeTime(date: Date | number, opts?: {
|
|
61
|
+
export declare function formatRelativeTime(date: Date | number | bigint, opts?: {
|
|
49
62
|
now?: Date;
|
|
50
63
|
style?: "short" | "long";
|
|
51
64
|
}): string;
|
|
65
|
+
/**
|
|
66
|
+
* Formats a date (or a unix-millisecond timestamp, `number` or `bigint`). `{ style: "date" }`
|
|
67
|
+
* (default) → `"Oct 3, 2026"`, the DateInput and table default; `{ style: "dateTime" }` →
|
|
68
|
+
* `"Oct 10, 3:04:05 PM"`, an event in the recent past. `locale` defaults to `"en-US"`;
|
|
69
|
+
* `timeZone` defaults to the runtime's (pass `"UTC"` when server and client must agree). An
|
|
70
|
+
* invalid date is returned as `formatNumber` prints `NaN`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function formatDate(date: Date | number | bigint, opts?: {
|
|
73
|
+
style?: "date" | "dateTime";
|
|
74
|
+
locale?: string;
|
|
75
|
+
timeZone?: string;
|
|
76
|
+
}): string;
|
|
52
77
|
/**
|
|
53
78
|
* Formats a ratio as a percentage. `0.1234` → `"12.3%"`. `precision` is the maximum fraction
|
|
54
79
|
* digits (default `1`).
|