@siyahi/ui 0.1.1-next.4 → 0.1.3-next.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/README.md +19 -8
- package/dist/components/registry/dashboardcn/bar-list.d.ts +2 -0
- package/dist/components/registry/dashboardcn/bar-list.js +30 -22
- package/dist/components/registry/niko-table/core/data-table-structure.js +2 -2
- package/dist/components/registry/niko-table/filters/table-column-actions.js +4 -4
- package/dist/components/registry/niko-table/filters/table-column-sort.js +3 -4
- package/dist/components/registry/niko-table/lib/styles.js +1 -1
- package/dist/components/siyahi/treemap.d.ts +16 -7
- package/dist/components/siyahi/treemap.js +34 -21
- package/dist/index.d.ts +2 -2
- package/dist/lib/treemap.d.ts +23 -0
- package/dist/lib/treemap.js +40 -0
- package/package.json +2 -1
- package/styles/fallback-fonts.css +65 -0
- package/styles/siyahi.css +9 -2
package/README.md
CHANGED
|
@@ -19,12 +19,14 @@ is Tailwind source, so a plain CSS import leaves every component unstyled.
|
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
21
|
npm install @siyahi/ui@next tailwindcss @tailwindcss/vite
|
|
22
|
+
npm install --save-dev @siyahi/tools@next
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
```ts
|
|
25
26
|
// vite.config.ts
|
|
26
27
|
import tailwindcss from "@tailwindcss/vite";
|
|
27
|
-
|
|
28
|
+
import { preloadFonts } from "@siyahi/tools/vite";
|
|
29
|
+
export default defineConfig({ plugins: [react(), tailwindcss(), preloadFonts()] });
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
```css
|
|
@@ -43,6 +45,14 @@ createRoot(root).render(
|
|
|
43
45
|
);
|
|
44
46
|
```
|
|
45
47
|
|
|
48
|
+
`preloadFonts()` adds `<link rel="preload">` tags for Geist and Geist Mono to
|
|
49
|
+
the built `index.html`, so the fonts download with the scripts instead of after
|
|
50
|
+
the first paint. Until they arrive the theme draws Arial (or its Linux twins,
|
|
51
|
+
Liberation Sans and Arimo) scaled to Geist's metrics, so nothing moves when
|
|
52
|
+
Geist swaps in. An app that renders its own HTML adds the tags itself, with
|
|
53
|
+
the hashed URLs of `geist-latin-wght-normal.woff2`,
|
|
54
|
+
`geist-latin-ext-wght-normal.woff2` and `geist-mono-latin-wght-normal.woff2`.
|
|
55
|
+
|
|
46
56
|
Everything comes from `@siyahi/ui`: the shadcn components, the registry
|
|
47
57
|
add-ons (data table, heatmaps, stat tiles, sidebar), Siyahi's own components
|
|
48
58
|
and the Recharts pieces charts are built from. Add `lucide-react` only if your
|
|
@@ -137,17 +147,18 @@ npm install --save-dev @siyahi/tools@next oxlint
|
|
|
137
147
|
```
|
|
138
148
|
|
|
139
149
|
`@siyahi/tools` also has `siyahi-shots` (screenshots of a page at 1920 and 390
|
|
140
|
-
pixels wide in both schemes, with layout checks)
|
|
150
|
+
pixels wide in both schemes, with layout checks), `siyahi-cls` (how far a page
|
|
151
|
+
moves after its first paint on a slow network) and `siyahi-contrast` (the
|
|
141
152
|
theme contrast check). See [packages/tools](packages/tools/README.md).
|
|
142
153
|
|
|
143
154
|
## This repository
|
|
144
155
|
|
|
145
|
-
| Path | What
|
|
146
|
-
| ----------------- |
|
|
147
|
-
| `packages/ui` | `@siyahi/ui`. The theme is `styles/siyahi.css`, the only file with colour values.
|
|
148
|
-
| `packages/tools` | `@siyahi/tools`: lint plugin,
|
|
149
|
-
| `apps/catalogue` | The catalogue site, a Vite app deployed as a Cloudflare Worker.
|
|
150
|
-
| `assets/icon.svg` | The mark.
|
|
156
|
+
| Path | What |
|
|
157
|
+
| ----------------- | ---------------------------------------------------------------------------------- |
|
|
158
|
+
| `packages/ui` | `@siyahi/ui`. The theme is `styles/siyahi.css`, the only file with colour values. |
|
|
159
|
+
| `packages/tools` | `@siyahi/tools`: lint plugin, font preload, contrast, screenshot and shift checks. |
|
|
160
|
+
| `apps/catalogue` | The catalogue site, a Vite app deployed as a Cloudflare Worker. |
|
|
161
|
+
| `assets/icon.svg` | The mark. |
|
|
151
162
|
|
|
152
163
|
Development uses pnpm and [Vite+](https://viteplus.dev):
|
|
153
164
|
|
|
@@ -6,6 +6,8 @@ export interface BarListItem {
|
|
|
6
6
|
/** Renders the label as a link. */
|
|
7
7
|
href?: string;
|
|
8
8
|
icon?: React$1.ReactNode;
|
|
9
|
+
/** Secondary figure after the label, such as a `Delta`. */
|
|
10
|
+
detail?: React$1.ReactNode;
|
|
9
11
|
/** Stable key when names can repeat. */
|
|
10
12
|
key?: string;
|
|
11
13
|
}
|
|
@@ -31,28 +31,36 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
|
|
|
31
31
|
className: "flex items-center gap-3 text-sm",
|
|
32
32
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
33
33
|
className: "relative flex h-8 min-w-0 flex-1 items-center",
|
|
34
|
-
children: [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
className: "
|
|
50
|
-
children: item.icon
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ jsx("div", {
|
|
36
|
+
"aria-hidden": "true",
|
|
37
|
+
className: "absolute inset-y-0 left-0 rounded-md transition-[width] duration-300",
|
|
38
|
+
style: {
|
|
39
|
+
width: `${width}%`,
|
|
40
|
+
backgroundColor: `color-mix(in oklab, ${color} 20%, transparent)`
|
|
41
|
+
}
|
|
42
|
+
}),
|
|
43
|
+
/* @__PURE__ */ jsxs(Label, {
|
|
44
|
+
...item.href ? { href: item.href } : {},
|
|
45
|
+
...onItemClick && !item.href ? {
|
|
46
|
+
type: "button",
|
|
47
|
+
onClick: () => onItemClick(item)
|
|
48
|
+
} : {},
|
|
49
|
+
className: cn("relative flex min-w-0 items-center gap-2 px-2 text-left", interactive && "hover:underline"),
|
|
50
|
+
children: [item.icon ? /* @__PURE__ */ jsx("span", {
|
|
51
|
+
className: "text-muted-foreground shrink-0 [&>svg]:size-4",
|
|
52
|
+
children: item.icon
|
|
53
|
+
}) : null, /* @__PURE__ */ jsx("span", {
|
|
54
|
+
className: "truncate",
|
|
55
|
+
children: item.name
|
|
56
|
+
})]
|
|
57
|
+
}),
|
|
58
|
+
item.detail ? /* @__PURE__ */ jsx("span", {
|
|
59
|
+
"data-slot": "bar-list-detail",
|
|
60
|
+
className: "text-muted-foreground relative shrink-0 pr-2 text-xs tabular-nums",
|
|
61
|
+
children: item.detail
|
|
62
|
+
}) : null
|
|
63
|
+
]
|
|
56
64
|
}), /* @__PURE__ */ jsxs("div", {
|
|
57
65
|
className: "flex shrink-0 items-center gap-2 tabular-nums",
|
|
58
66
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -27,7 +27,7 @@ const DataTableHeader = React.memo(function DataTableHeader({ className, sticky
|
|
|
27
27
|
const flexColumnIds = resolveFlexColumnIds(table);
|
|
28
28
|
const columnSizing = table.state.columnSizing;
|
|
29
29
|
return /* @__PURE__ */ jsx(TableHeader, {
|
|
30
|
-
className: cn(sticky && "sticky top-0 z-30 bg-
|
|
30
|
+
className: cn(sticky && "sticky top-0 z-30 bg-card", sticky && "after:absolute after:right-0 after:bottom-0 after:left-0 after:h-px after:bg-border", className),
|
|
31
31
|
children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => {
|
|
32
32
|
const isFlex = flexColumnIds.has(header.column.id);
|
|
33
33
|
const headerStyle = {
|
|
@@ -83,7 +83,7 @@ const BodyRow = React.memo(function BodyRow({ row, displayIndex, expandColumnId,
|
|
|
83
83
|
"data-flash": flashing ? "true" : void 0,
|
|
84
84
|
"data-col-id": cell.column.id,
|
|
85
85
|
style: cellStyle,
|
|
86
|
-
className: cn(!cell.getIsGrouped() && "truncate", cell.column.getIsPinned() && "bg-
|
|
86
|
+
className: cn(!cell.getIsGrouped() && "truncate", cell.column.getIsPinned() && "bg-linear-to-r group-hover:from-muted/50 group-hover:to-muted/50 group-data-[context-menu-open]:from-muted/50 group-data-[context-menu-open]:to-muted/50 group-data-[state=selected]:from-muted group-data-[state=selected]:to-muted"),
|
|
87
87
|
children: renderCellContent(cell)
|
|
88
88
|
}, cell.id);
|
|
89
89
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Button } from "../../../ui/button.js";
|
|
2
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
|
|
2
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
|
|
3
3
|
import { cn } from "../../../../lib/utils.js";
|
|
4
4
|
import "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -34,13 +34,13 @@ function TableColumnActions({ children, className, label = "Column Actions", isA
|
|
|
34
34
|
className: "sr-only",
|
|
35
35
|
children: label
|
|
36
36
|
})]
|
|
37
|
-
}) }), /* @__PURE__ */
|
|
37
|
+
}) }), /* @__PURE__ */ jsx(DropdownMenuContent, {
|
|
38
38
|
align,
|
|
39
39
|
className: "w-48",
|
|
40
|
-
children: [/* @__PURE__ */ jsx(DropdownMenuLabel, {
|
|
40
|
+
children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, {
|
|
41
41
|
className: "text-xs font-normal text-muted-foreground",
|
|
42
42
|
children: label
|
|
43
|
-
}), children]
|
|
43
|
+
}), children] })
|
|
44
44
|
})] });
|
|
45
45
|
}
|
|
46
46
|
TableColumnActions.displayName = "TableColumnActions";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Button } from "../../../ui/button.js";
|
|
3
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
|
|
3
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
|
|
4
4
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../../../ui/tooltip.js";
|
|
5
5
|
import { cn } from "../../../../lib/utils.js";
|
|
6
6
|
import { FILTER_VARIANTS } from "../lib/constants.js";
|
|
@@ -76,8 +76,7 @@ function TableColumnSortOptions({ column, table: propTable, variant: propVariant
|
|
|
76
76
|
column.toggleSorting(isDesc, canMultiSort ? isMulti : false);
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
80
|
-
withSeparator && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
79
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [withSeparator && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}), /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
81
80
|
/* @__PURE__ */ jsxs(DropdownMenuLabel, {
|
|
82
81
|
className: "flex items-center justify-between text-xs font-normal text-muted-foreground",
|
|
83
82
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -122,7 +121,7 @@ function TableColumnSortOptions({ column, table: propTable, variant: propVariant
|
|
|
122
121
|
onClick: () => column.clearSorting(),
|
|
123
122
|
children: [/* @__PURE__ */ jsx(icons.unsorted, { className: "mr-2 size-4 text-muted-foreground/70" }), "Clear Sort"]
|
|
124
123
|
})
|
|
125
|
-
] });
|
|
124
|
+
] })] });
|
|
126
125
|
}
|
|
127
126
|
/**
|
|
128
127
|
* Standalone dropdown menu for sorting.
|
|
@@ -16,7 +16,7 @@ const getCommonPinningStyles = (column, isHeader = false) => {
|
|
|
16
16
|
maxWidth: columnSize,
|
|
17
17
|
flexShrink: 0,
|
|
18
18
|
zIndex: isHeader ? 20 : 10,
|
|
19
|
-
backgroundColor: "var(--
|
|
19
|
+
backgroundColor: "var(--card)",
|
|
20
20
|
...isLeft ? { boxShadow: "inset -2px 0 0 0 color-mix(in oklab, var(--foreground) 40%, transparent), 4px 0 8px -2px color-mix(in oklab, var(--foreground) 14%, transparent)" } : { boxShadow: "inset 2px 0 0 0 color-mix(in oklab, var(--foreground) 40%, transparent), -4px 0 8px -2px color-mix(in oklab, var(--foreground) 14%, transparent)" }
|
|
21
21
|
};
|
|
22
22
|
};
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
//#region src/components/siyahi/treemap.d.ts
|
|
2
2
|
export interface TreemapItem {
|
|
3
3
|
name: string;
|
|
4
|
-
/** Tile area, such as the holding's value. */
|
|
4
|
+
/** Tile area, such as the holding's value. Zero, negative and non-finite weights draw no tile. */
|
|
5
5
|
weight: number;
|
|
6
|
-
/** Signed change as a fraction; sets the heat. */
|
|
7
|
-
change: number;
|
|
6
|
+
/** Signed change as a fraction; sets the heat. `null` when unknown: a muted tile marked "—". */
|
|
7
|
+
change: number | null;
|
|
8
|
+
/** Unique key when names repeat, such as one symbol held at two brokers. Defaults to `name`. */
|
|
9
|
+
key?: string;
|
|
10
|
+
/** Tiles of one group, such as a sector, sit together under the group's name, even a group of one. */
|
|
11
|
+
group?: string;
|
|
8
12
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
items: TreemapItem[];
|
|
13
|
+
export interface TreemapProps<T extends TreemapItem> {
|
|
14
|
+
items: T[];
|
|
12
15
|
height: number;
|
|
13
|
-
|
|
16
|
+
/** ±range: the change, as a fraction, that takes the deepest heat step. Default 0.05 (±5%); a range that is not a positive number uses the default. */
|
|
17
|
+
range?: number;
|
|
18
|
+
/** Gets the item under the pointer, and null when the pointer moves onto a group's name or leaves the map. */
|
|
19
|
+
onHover?: (item: T | null) => void;
|
|
20
|
+
}
|
|
21
|
+
/** Holdings heat map: area by weight, colour by signed change, optionally grouped; hand-drawn SVG. */
|
|
22
|
+
export declare function Treemap<T extends TreemapItem>({ items, height, range, onHover }: TreemapProps<T>): import("react").JSX.Element;
|
|
14
23
|
//#endregion
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { useFormat } from "../../lib/format.js";
|
|
2
|
+
import { heat, layout } from "../../lib/treemap.js";
|
|
2
3
|
import { useLayoutEffect, useRef, useState } from "react";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { hierarchy, treemap, treemapSquarify } from "d3-hierarchy";
|
|
5
5
|
//#region src/components/siyahi/treemap.tsx
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const mix = Math.min(5, Math.ceil(Math.abs(change) * 100)) * 12;
|
|
9
|
-
return `color-mix(in oklab, var(${change > 0 ? "--positive" : "--negative"}) ${mix}%, var(--card))`;
|
|
10
|
-
}
|
|
11
|
-
/** Holdings heat map: area by weight, colour by signed change, hand-drawn SVG. */
|
|
12
|
-
function Treemap({ items, height }) {
|
|
6
|
+
/** Holdings heat map: area by weight, colour by signed change, optionally grouped; hand-drawn SVG. */
|
|
7
|
+
function Treemap({ items, height, range, onHover }) {
|
|
13
8
|
const ref = useRef(null);
|
|
14
9
|
const [width, setWidth] = useState(0);
|
|
15
10
|
const { pct } = useFormat();
|
|
@@ -18,39 +13,57 @@ function Treemap({ items, height }) {
|
|
|
18
13
|
if (ref.current) observer.observe(ref.current);
|
|
19
14
|
return () => observer.disconnect();
|
|
20
15
|
}, []);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
16
|
+
const { groups, tiles } = layout(items, width, height);
|
|
17
|
+
const change = (value) => value === null ? "—" : `${value > 0 ? "▲ " : value < 0 ? "▼ " : ""}${pct(Math.abs(value))}`;
|
|
23
18
|
return /* @__PURE__ */ jsx("div", {
|
|
24
19
|
ref,
|
|
25
20
|
"data-slot": "treemap",
|
|
26
21
|
style: { height },
|
|
27
|
-
children: /* @__PURE__ */
|
|
22
|
+
children: /* @__PURE__ */ jsxs("svg", {
|
|
28
23
|
width,
|
|
29
24
|
height,
|
|
30
25
|
role: "img",
|
|
31
26
|
"aria-label": "Treemap of holdings by weight and change",
|
|
32
27
|
className: "text-xs",
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
onPointerLeave: () => onHover?.(null),
|
|
29
|
+
children: [groups.map(({ group, ...box }) => /* @__PURE__ */ jsxs("svg", {
|
|
30
|
+
...box,
|
|
31
|
+
"data-slot": "treemap-group",
|
|
32
|
+
onPointerEnter: () => onHover?.(null),
|
|
33
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
34
|
+
width: "100%",
|
|
35
|
+
height: "100%",
|
|
36
|
+
fill: "none",
|
|
37
|
+
pointerEvents: "all"
|
|
38
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
39
|
+
x: 2,
|
|
40
|
+
y: 12,
|
|
41
|
+
className: "fill-muted-foreground font-medium",
|
|
42
|
+
children: group
|
|
43
|
+
})]
|
|
44
|
+
}, group)), tiles.map(({ item, ...box }) => /* @__PURE__ */ jsxs("svg", {
|
|
45
|
+
...box,
|
|
46
|
+
"data-slot": "treemap-tile",
|
|
47
|
+
onPointerEnter: () => onHover?.(item),
|
|
35
48
|
children: [/* @__PURE__ */ jsx("rect", {
|
|
36
|
-
width:
|
|
37
|
-
height:
|
|
49
|
+
width: "100%",
|
|
50
|
+
height: "100%",
|
|
38
51
|
rx: 4,
|
|
39
|
-
style: { fill: heat(
|
|
40
|
-
}),
|
|
52
|
+
style: { fill: heat(item.change, range) }
|
|
53
|
+
}), box.width > 56 && box.height > 36 && /* @__PURE__ */ jsxs("text", {
|
|
41
54
|
x: 8,
|
|
42
55
|
y: 18,
|
|
43
56
|
className: "fill-foreground",
|
|
44
57
|
children: [/* @__PURE__ */ jsx("tspan", {
|
|
45
58
|
className: "font-medium",
|
|
46
|
-
children:
|
|
47
|
-
}), /* @__PURE__ */
|
|
59
|
+
children: item.name
|
|
60
|
+
}), /* @__PURE__ */ jsx("tspan", {
|
|
48
61
|
x: 8,
|
|
49
62
|
dy: 16,
|
|
50
|
-
children:
|
|
63
|
+
children: change(item.change)
|
|
51
64
|
})]
|
|
52
65
|
})]
|
|
53
|
-
},
|
|
66
|
+
}, item.key ?? item.name))]
|
|
54
67
|
})
|
|
55
68
|
});
|
|
56
69
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ import { LocalTime, LocalTimeProps } from "./components/siyahi/local-time.js";
|
|
|
43
43
|
import { PriceChart, PriceChartProps } from "./components/siyahi/price-chart.js";
|
|
44
44
|
import { SiyahiLocale, defaultLocale } from "./lib/locale.js";
|
|
45
45
|
import { SiyahiProvider, SiyahiProviderProps, useLocale } from "./components/siyahi/siyahi-provider.js";
|
|
46
|
-
import { Treemap, TreemapItem } from "./components/siyahi/treemap.js";
|
|
46
|
+
import { Treemap, TreemapItem, TreemapProps } from "./components/siyahi/treemap.js";
|
|
47
47
|
import { Alert, AlertAction, AlertDescription, AlertTitle } from "./components/ui/alert.js";
|
|
48
48
|
import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from "./components/ui/avatar.js";
|
|
49
49
|
import { Badge, badgeVariants } from "./components/ui/badge.js";
|
|
@@ -70,4 +70,4 @@ import { Toggle, toggleVariants } from "./components/ui/toggle.js";
|
|
|
70
70
|
import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group.js";
|
|
71
71
|
import { Formatters, TimeOptions, money, moneyCompact, pct, time, useFormat } from "./lib/format.js";
|
|
72
72
|
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Line, LineChart, ReferenceLine, XAxis, YAxis } from "./lib/recharts.js";
|
|
73
|
-
export { ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, Area, AreaChart, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Bar, BarChart, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CartesianGrid, ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowMenuScope, DataTableSkeleton, DataTableSkeletonProps, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, Labels, Line, LineChart, LocalTime, LocalTimeProps, NavMain, NavProjects, NavUser, type Option, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, PriceChartProps, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, type QueryKeys, ReferenceLine, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScrollAlign, ScrollArea, ScrollBar, type ScrollEvent, ScrollRowIntoView, SectionCard, SectionCards, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiLocale, SiyahiProvider, SiyahiProviderProps, Skeleton, Slider, StatusActivity, StatusColorConfig, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBlockProps, StatusHeatmapBody, StatusHeatmapBodyProps, StatusHeatmapFooter, StatusHeatmapFooterProps, StatusHeatmapLabels, StatusHeatmapLegend, StatusHeatmapLegendProps, StatusHeatmapProps, StatusHeatmapStat, StatusHeatmapStatProps, StatusValue, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnActionsProps, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFacetedFilterProps, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TeamSwitcher, Textarea, TimeOptions, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapItem, type ValueOf, type ColorConfig$1 as WeekdayColorConfig, type WeekdayExtraColumnSpec, type WeekdayExtraRowSpec, WeekdayHeatmap, WeekdayHeatmapBlock, type WeekdayHeatmapBlockProps, WeekdayHeatmapBody, type WeekdayHeatmapBodyProps, WeekdayHeatmapFooter, type WeekdayHeatmapFooterProps, type WeekdayHeatmapLabels, WeekdayHeatmapLegend, type WeekdayHeatmapLegendProps, type WeekdayHeatmapProps, WeekdayHeatmapStat, type WeekdayHeatmapStatProps, type WeekdayHour, type WeekdayHourlyActivity, type WeekdayIndex, XAxis, YAxis, badgeVariants, buttonVariants, defaultLocale, flashCellKey, money, moneyCompact, pct, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, tabsListVariants, time, toggleVariants, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useTableFacetedFilter };
|
|
73
|
+
export { ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, Area, AreaChart, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Bar, BarChart, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CartesianGrid, ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowMenuScope, DataTableSkeleton, DataTableSkeletonProps, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, Labels, Line, LineChart, LocalTime, LocalTimeProps, NavMain, NavProjects, NavUser, type Option, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, PriceChartProps, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, type QueryKeys, ReferenceLine, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScrollAlign, ScrollArea, ScrollBar, type ScrollEvent, ScrollRowIntoView, SectionCard, SectionCards, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiLocale, SiyahiProvider, SiyahiProviderProps, Skeleton, Slider, StatusActivity, StatusColorConfig, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBlockProps, StatusHeatmapBody, StatusHeatmapBodyProps, StatusHeatmapFooter, StatusHeatmapFooterProps, StatusHeatmapLabels, StatusHeatmapLegend, StatusHeatmapLegendProps, StatusHeatmapProps, StatusHeatmapStat, StatusHeatmapStatProps, StatusValue, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnActionsProps, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFacetedFilterProps, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TeamSwitcher, Textarea, TimeOptions, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapItem, TreemapProps, type ValueOf, type ColorConfig$1 as WeekdayColorConfig, type WeekdayExtraColumnSpec, type WeekdayExtraRowSpec, WeekdayHeatmap, WeekdayHeatmapBlock, type WeekdayHeatmapBlockProps, WeekdayHeatmapBody, type WeekdayHeatmapBodyProps, WeekdayHeatmapFooter, type WeekdayHeatmapFooterProps, type WeekdayHeatmapLabels, WeekdayHeatmapLegend, type WeekdayHeatmapLegendProps, type WeekdayHeatmapProps, WeekdayHeatmapStat, type WeekdayHeatmapStatProps, type WeekdayHour, type WeekdayHourlyActivity, type WeekdayIndex, XAxis, YAxis, badgeVariants, buttonVariants, defaultLocale, flashCellKey, money, moneyCompact, pct, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, tabsListVariants, time, toggleVariants, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useTableFacetedFilter };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/lib/treemap.d.ts
|
|
2
|
+
interface Box {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Layout<T> {
|
|
9
|
+
groups: (Box & {
|
|
10
|
+
group: string;
|
|
11
|
+
})[];
|
|
12
|
+
tiles: (Box & {
|
|
13
|
+
item: T;
|
|
14
|
+
})[];
|
|
15
|
+
}
|
|
16
|
+
/** Squarified layout: items without a group are tiles of their own, the rest sit together under their group's label. */
|
|
17
|
+
export declare function layout<T extends {
|
|
18
|
+
weight: number;
|
|
19
|
+
group?: string;
|
|
20
|
+
}>(items: T[], width: number, height: number): Layout<T>;
|
|
21
|
+
export declare function heat(change: number | null, range?: number): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { hierarchy, treemap, treemapSquarify } from "d3-hierarchy";
|
|
2
|
+
//#region src/lib/treemap.ts
|
|
3
|
+
/** Height of a group's label row, above its tiles. */
|
|
4
|
+
const GROUP_LABEL = 18;
|
|
5
|
+
const box = ({ x0, y0, x1, y1 }) => ({
|
|
6
|
+
x: x0,
|
|
7
|
+
y: y0,
|
|
8
|
+
width: x1 - x0,
|
|
9
|
+
height: y1 - y0
|
|
10
|
+
});
|
|
11
|
+
const area = (weight) => weight !== void 0 && Number.isFinite(weight) && weight > 0 ? weight : 0;
|
|
12
|
+
/** Squarified layout: items without a group are tiles of their own, the rest sit together under their group's label. */
|
|
13
|
+
function layout(items, width, height) {
|
|
14
|
+
const nested = { children: [...Map.groupBy(items, (item) => item.group)].flatMap(([group, members]) => {
|
|
15
|
+
const tiles = members.map((item) => ({ item }));
|
|
16
|
+
return group === void 0 ? tiles : [{
|
|
17
|
+
group,
|
|
18
|
+
children: tiles
|
|
19
|
+
}];
|
|
20
|
+
}) };
|
|
21
|
+
const root = treemap().size([width, height]).paddingInner(2).paddingTop(({ data }) => data.group === void 0 ? 0 : GROUP_LABEL).tile(treemapSquarify)(hierarchy(nested).sum(({ item }) => area(item?.weight)));
|
|
22
|
+
return {
|
|
23
|
+
groups: (root.children ?? []).flatMap((node) => node.data.group === void 0 || !node.value ? [] : [{
|
|
24
|
+
...box(node),
|
|
25
|
+
height: GROUP_LABEL,
|
|
26
|
+
group: node.data.group
|
|
27
|
+
}]),
|
|
28
|
+
tiles: root.leaves().flatMap((node) => node.data.item === void 0 || !node.value ? [] : [{
|
|
29
|
+
...box(node),
|
|
30
|
+
item: node.data.item
|
|
31
|
+
}])
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function heat(change, range = .05) {
|
|
35
|
+
if (!change) return "var(--muted)";
|
|
36
|
+
const mix = Math.min(5, Math.ceil(Math.abs(change) / (Number.isFinite(range) && range > 0 ? range : .05) * 5)) * 12;
|
|
37
|
+
return `color-mix(in oklab, var(${change > 0 ? "--positive" : "--negative"}) ${mix}%, var(--card))`;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { heat, layout };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siyahi/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-next.1",
|
|
4
4
|
"description": "Stock shadcn/ui on Base UI and Tailwind v4, a finance theme, a few compositions and formatters.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"base-ui",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"tw-animate-css": "^1.4.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
+
"@tailwindcss/node": "4.3.3",
|
|
61
62
|
"@types/d3-hierarchy": "^3.1.7",
|
|
62
63
|
"@types/node": "24.19.2",
|
|
63
64
|
"@types/react": "~19.3.0",
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Generated by scripts/generate.ts. Do not edit.
|
|
3
|
+
* System fonts scaled to Geist's and Geist Mono's metrics. The theme names
|
|
4
|
+
* them right after Geist, so the text a browser draws while Geist loads takes
|
|
5
|
+
* the space Geist will, and nothing moves when Geist swaps in.
|
|
6
|
+
*/
|
|
7
|
+
@font-face {
|
|
8
|
+
font-family: "Geist Fallback";
|
|
9
|
+
src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("LiberationSans"), local("Arimo Regular"), local("Arimo-Regular");
|
|
10
|
+
font-weight: 100 450;
|
|
11
|
+
size-adjust: 102.87%;
|
|
12
|
+
ascent-override: 97.7%;
|
|
13
|
+
descent-override: 28.68%;
|
|
14
|
+
line-gap-override: 0%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: "Geist Fallback";
|
|
19
|
+
src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("LiberationSans"), local("Arimo Regular"), local("Arimo-Regular");
|
|
20
|
+
font-weight: 451 550;
|
|
21
|
+
size-adjust: 105.29%;
|
|
22
|
+
ascent-override: 95.45%;
|
|
23
|
+
descent-override: 28.02%;
|
|
24
|
+
line-gap-override: 0%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@font-face {
|
|
28
|
+
font-family: "Geist Fallback";
|
|
29
|
+
src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"), local("LiberationSans-Bold"), local("Arimo Bold"), local("Arimo-Bold");
|
|
30
|
+
font-weight: 551 650;
|
|
31
|
+
size-adjust: 100.05%;
|
|
32
|
+
ascent-override: 100.45%;
|
|
33
|
+
descent-override: 29.49%;
|
|
34
|
+
line-gap-override: 0%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@font-face {
|
|
38
|
+
font-family: "Geist Fallback";
|
|
39
|
+
src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"), local("LiberationSans-Bold"), local("Arimo Bold"), local("Arimo-Bold");
|
|
40
|
+
font-weight: 651 900;
|
|
41
|
+
size-adjust: 102.09%;
|
|
42
|
+
ascent-override: 98.44%;
|
|
43
|
+
descent-override: 28.9%;
|
|
44
|
+
line-gap-override: 0%;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@font-face {
|
|
48
|
+
font-family: "Geist Mono Fallback";
|
|
49
|
+
src: local("Courier New"), local("CourierNewPSMT"), local("Liberation Mono"), local("LiberationMono"), local("Cousine Regular"), local("Cousine-Regular");
|
|
50
|
+
font-weight: 100 550;
|
|
51
|
+
size-adjust: 99.98%;
|
|
52
|
+
ascent-override: 100.52%;
|
|
53
|
+
descent-override: 29.5%;
|
|
54
|
+
line-gap-override: 0%;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@font-face {
|
|
58
|
+
font-family: "Geist Mono Fallback";
|
|
59
|
+
src: local("Courier New Bold"), local("CourierNewPS-BoldMT"), local("Liberation Mono Bold"), local("LiberationMono-Bold"), local("Cousine Bold"), local("Cousine-Bold");
|
|
60
|
+
font-weight: 551 900;
|
|
61
|
+
size-adjust: 99.98%;
|
|
62
|
+
ascent-override: 100.52%;
|
|
63
|
+
descent-override: 29.5%;
|
|
64
|
+
line-gap-override: 0%;
|
|
65
|
+
}
|
package/styles/siyahi.css
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
@import "./shadcn.css";
|
|
10
10
|
@import "@fontsource-variable/geist";
|
|
11
11
|
@import "@fontsource-variable/geist-mono";
|
|
12
|
+
@import "./fallback-fonts.css";
|
|
12
13
|
|
|
13
14
|
/* Tailwind does not scan node_modules, so name the package's own classes. */
|
|
14
15
|
@source "../dist";
|
|
@@ -21,9 +22,15 @@
|
|
|
21
22
|
@custom-variant dark (@media (prefers-color-scheme: dark));
|
|
22
23
|
|
|
23
24
|
@theme inline {
|
|
24
|
-
--font-sans: "Geist Variable", ui-sans-serif, system-ui, sans-serif;
|
|
25
|
-
--font-mono: "Geist Mono Variable", ui-monospace, monospace;
|
|
25
|
+
--font-sans: "Geist Variable", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
|
|
26
|
+
--font-mono: "Geist Mono Variable", "Geist Mono Fallback", ui-monospace, monospace;
|
|
26
27
|
--font-heading: var(--font-sans);
|
|
28
|
+
/*
|
|
29
|
+
* Tailwind's 65ch, measured in Geist, whose "0" is 0.663em wide. A ch
|
|
30
|
+
* follows whichever font is drawing, so a plain 65ch is narrower while the
|
|
31
|
+
* fallback draws and every prose block rewraps when Geist arrives.
|
|
32
|
+
*/
|
|
33
|
+
--max-width-prose: 43.1em;
|
|
27
34
|
--color-background: var(--background);
|
|
28
35
|
--color-foreground: var(--foreground);
|
|
29
36
|
--color-card: var(--card);
|