@vvedantb/ui 0.24.0 → 0.25.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 +21 -9
- package/package.json +1 -1
- package/src/brand/AppIcons.tsx +11 -9
- package/src/brand/AppMark.tsx +3 -5
- package/src/brand/index.ts +3 -0
- package/src/brand/svg.ts +41 -12
- package/src/brand/vProAppBenefits.ts +1 -3
package/README.md
CHANGED
|
@@ -879,7 +879,7 @@ links under a separator.
|
|
|
879
879
|
### `Icon*` app icons
|
|
880
880
|
|
|
881
881
|
Tabler-style plain app glyphs: `IconVibot`, `IconVhub`, `IconVmem`, `IconVerve`,
|
|
882
|
-
`IconVelth` and `IconProjectV`. No background,
|
|
882
|
+
`IconVelth` and `IconProjectV`. No background. Each sits on an equalised square viewBox, so all apps look the same size. `APP_ICONS[app]`
|
|
883
883
|
looks one up by `AppName`.
|
|
884
884
|
|
|
885
885
|
```tsx
|
|
@@ -888,24 +888,36 @@ import { IconVerve } from "@vvedantb/ui"
|
|
|
888
888
|
<IconVerve size={24} color="currentColor" />
|
|
889
889
|
```
|
|
890
890
|
|
|
891
|
-
`size`
|
|
891
|
+
`size` sets both width and height (default 24; a string is any CSS length). `color`
|
|
892
892
|
defaults to `currentColor`. `stroke` sets the stroke width in pixels for stroke
|
|
893
893
|
glyphs (fill glyphs ignore it). `title` gives an accessible name. The ref goes
|
|
894
894
|
to the `<svg>`.
|
|
895
895
|
|
|
896
|
+
`align?: "center" | "start"` (0.25.1, default `"center"`) sets where the glyph sits
|
|
897
|
+
in its equal-size square. `"start"` left-aligns the glyph's ink in the same square
|
|
898
|
+
(same scale, same `size` x `size` box), so labels line up in a vertical list.
|
|
899
|
+
`APP_MARK_VIEWBOX_START` holds the viewBoxes.
|
|
900
|
+
|
|
901
|
+
```tsx
|
|
902
|
+
<IconVmem size={16} align="start" />
|
|
903
|
+
```
|
|
904
|
+
|
|
896
905
|
### `AppMark` (deprecated)
|
|
897
906
|
|
|
898
907
|
Deprecated in favour of the `Icon*` components for plain marks. Tiles stay here.
|
|
899
908
|
Family app icons: `app` (`projectv`, `vibot`, `vhub`, `vmem`, `verve`, `velth`),
|
|
900
909
|
`variant`, `size`, `title`.
|
|
901
910
|
|
|
902
|
-
- `variant="mark"` (default) is the plain logo in `currentColor`. It
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
911
|
+
- `variant="mark"` (default) is the plain logo in `currentColor`. It sits
|
|
912
|
+
on a square viewBox. The five apps (`vibot`, `vhub`, `vmem`, `verve`, `velth`) keep one
|
|
913
|
+
frame size, 629 x 629 (`APP_MARK_CROP_VIEWBOX` is the historical `173 197 629 629`), so relative
|
|
914
|
+
glyph sizes match the tiles. Each viewBox origin is centred on that glyph's `markBBox`, so no
|
|
915
|
+
glyph sits off-centre in its square. `projectv` is a brand mark, so it keeps its own 687 frame,
|
|
916
|
+
centred on its bbox (`PROJECTV_MARK_VIEWBOX`, `171.5 181 687 687`). `size` sets both width and
|
|
917
|
+
height; a string `size` (for example `"2rem"`) is any CSS length. `APP_MARK_VIEWBOX` holds the
|
|
918
|
+
viewBox for each app; `appMarkSvg()` and `APP_MARK_SVG` use it. `markAspect` returns
|
|
919
|
+
1 and is kept for API stability only.
|
|
920
|
+
- `variant="tile"` and `"tile-light"` use the same 1024 grid on a
|
|
909
921
|
rounded tile, always square. `appTileSvg`, `appAdaptiveSvg`, `appExtension128Svg`,
|
|
910
922
|
`APP_TILE_SVG`, `APP_TILE_LIGHT_SVG` and favicons are unchanged.
|
|
911
923
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vvedantb/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared React 19 UI for web apps: one JavaScript entry (primitives, shell pieces, app helpers including the Convex and Clerk provider, VITE env parsing and ensure-user, artifact viewers over the @vvedantb/server artifacts core, native tokens), design-token CSS, shared Tailwind v4 CSS and a Tailwind preset.",
|
|
6
6
|
"type": "module",
|
package/src/brand/AppIcons.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { forwardRef, useId, type ForwardRefExoticComponent, type RefAttributes, type SVGProps } from "react";
|
|
2
|
-
import { APP_MARKS, APP_MARK_VIEWBOX,
|
|
2
|
+
import { APP_MARKS, APP_MARK_VIEWBOX, APP_MARK_VIEWBOX_START, APP_NAMES, markLinecap, markStrokeWidth, type AppName } from "./svg";
|
|
3
3
|
|
|
4
4
|
export type AppIconProps = Omit<SVGProps<SVGSVGElement>, "children" | "height" | "width" | "viewBox" | "stroke" | "color"> & {
|
|
5
|
-
/** Rendered height. Default 24. A number
|
|
5
|
+
/** Rendered width and height (the glyph is square). Default 24. A number is in pixels; a string is any CSS length. */
|
|
6
6
|
size?: number | string;
|
|
7
7
|
/** Glyph colour, for fill and stroke glyphs. Default `"currentColor"`. */
|
|
8
8
|
color?: string;
|
|
@@ -10,24 +10,25 @@ export type AppIconProps = Omit<SVGProps<SVGSVGElement>, "children" | "height" |
|
|
|
10
10
|
stroke?: number | string;
|
|
11
11
|
/** Accessible name. Without it the icon is `aria-hidden`. */
|
|
12
12
|
title?: string;
|
|
13
|
+
/** Where the glyph sits in its equal-size square. `"center"` (default) centres it. `"start"` left-aligns the glyph's ink in the same square, so labels line up in a vertical list. The rendered box stays `size` x `size`. */
|
|
14
|
+
align?: "center" | "start";
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export type AppIconComponent = ForwardRefExoticComponent<AppIconProps & RefAttributes<SVGSVGElement>>;
|
|
16
18
|
|
|
17
|
-
function
|
|
19
|
+
function viewBoxSide(app: AppName): number {
|
|
18
20
|
return Number(APP_MARK_VIEWBOX[app].split(" ")[3]);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
function createAppIcon(app: AppName, displayName: string): AppIconComponent {
|
|
22
24
|
const Icon = forwardRef<SVGSVGElement, AppIconProps>(function Icon(
|
|
23
|
-
{ size = 24, color = "currentColor", stroke, title, ...rest },
|
|
25
|
+
{ size = 24, color = "currentColor", stroke, title, align = "center", ...rest },
|
|
24
26
|
ref,
|
|
25
27
|
) {
|
|
26
28
|
const titleId = useId();
|
|
27
29
|
const { kind, paths } = APP_MARKS[app];
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const strokeWidth = stroke === undefined ? markStrokeWidth(app) : Number(stroke) * (viewBoxHeight(app) / renderedHeight);
|
|
30
|
+
const renderedSize = typeof size === "number" ? size : 24;
|
|
31
|
+
const strokeWidth = stroke === undefined ? markStrokeWidth(app) : Number(stroke) * (viewBoxSide(app) / renderedSize);
|
|
31
32
|
const glyphProps =
|
|
32
33
|
kind === "fill"
|
|
33
34
|
? { fill: color }
|
|
@@ -37,11 +38,12 @@ function createAppIcon(app: AppName, displayName: string): AppIconComponent {
|
|
|
37
38
|
{...rest}
|
|
38
39
|
ref={ref}
|
|
39
40
|
xmlns="http://www.w3.org/2000/svg"
|
|
40
|
-
width={
|
|
41
|
+
width={size}
|
|
41
42
|
height={size}
|
|
42
|
-
viewBox={APP_MARK_VIEWBOX[app]}
|
|
43
|
+
viewBox={align === "start" ? APP_MARK_VIEWBOX_START[app] : APP_MARK_VIEWBOX[app]}
|
|
43
44
|
preserveAspectRatio="xMidYMid meet"
|
|
44
45
|
data-app={app}
|
|
46
|
+
data-align={align}
|
|
45
47
|
role={title ? "img" : undefined}
|
|
46
48
|
aria-hidden={title ? undefined : true}
|
|
47
49
|
aria-labelledby={title ? titleId : undefined}
|
package/src/brand/AppMark.tsx
CHANGED
|
@@ -5,12 +5,10 @@ import { APP_MARKS, MARK_VIEWBOX, TILE_RADIUS, markLinecap, markStrokeWidth, typ
|
|
|
5
5
|
export type AppMarkProps = Omit<SVGProps<SVGSVGElement>, "children" | "height" | "width" | "viewBox"> & {
|
|
6
6
|
/** Which family app's mark to draw. */
|
|
7
7
|
app: AppName;
|
|
8
|
-
/** `"mark"` (default): plain logo in `currentColor
|
|
8
|
+
/** `"mark"` (default): plain logo in `currentColor` on an equalised square viewBox, so every app looks the same size. `"tile"`: white glyph on a black rounded tile. `"tile-light"`: black glyph on a white tile. */
|
|
9
9
|
variant?: AppMarkVariant;
|
|
10
10
|
/**
|
|
11
|
-
* Default 24.
|
|
12
|
-
* (a number gives an exact width; a string sets both to the same value and the glyph is centred).
|
|
13
|
-
* Tiles are always square, `size` by `size`.
|
|
11
|
+
* Default 24. Sets both width and height, for marks and tiles alike (always square). A string is any CSS length.
|
|
14
12
|
*/
|
|
15
13
|
size?: number | string;
|
|
16
14
|
/** Accessible name. Without it the mark is `aria-hidden`. */
|
|
@@ -23,7 +21,7 @@ const TILE_TONES = {
|
|
|
23
21
|
} as const;
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
|
-
* One of the six family app marks. The plain mark
|
|
24
|
+
* One of the six family app marks. The plain mark and the tiles share the same square 1024 viewBox, so a bare glyph matches the tile glyph optically.
|
|
27
25
|
* @deprecated Use the per-app `Icon*` components (or `APP_ICONS[app]`) for plain marks. Tiles are for app and store icons only.
|
|
28
26
|
*/
|
|
29
27
|
export function AppMark({ app, variant = "mark", size = 24, title, ...rest }: AppMarkProps) {
|
package/src/brand/index.ts
CHANGED
package/src/brand/svg.ts
CHANGED
|
@@ -5,7 +5,7 @@ export const APP_NAMES = ["projectv", "vibot", "vhub", "vmem", "verve", "velth"]
|
|
|
5
5
|
|
|
6
6
|
export type AppName = (typeof APP_NAMES)[number];
|
|
7
7
|
|
|
8
|
-
/** `mark`: glyph only
|
|
8
|
+
/** `mark`: glyph only on an equalised square viewBox, follows `currentColor`. `tile`: white glyph on a black tile. `tile-light`: black glyph on a white tile. */
|
|
9
9
|
export type AppMarkVariant = "mark" | "tile" | "tile-light";
|
|
10
10
|
|
|
11
11
|
export const MARK_VIEWBOX = "0 0 1024 1024";
|
|
@@ -175,20 +175,49 @@ export function markBBox(app: AppName): Box {
|
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
178
|
+
* Frame size for the five app glyphs (`vibot`, `vhub`, `vmem`, `verve`, `velth`) in the plain logo (`variant="mark"`,
|
|
179
|
+
* `appMarkSvg`, `Icon*`): a 629 x 629 square, the union of their `markBBox` results on the 1024 tile grid
|
|
180
|
+
* (x 186 to 789, y 259.96 to 761.7) at side max(width, height) x 1.04 (about 4% padding), rounded outward.
|
|
181
|
+
* All five use this side, so glyph scale stays equal. Only the size is shared: each app has its own origin in
|
|
182
|
+
* `APP_MARK_VIEWBOX`. `projectv` is left out so its wide brand mark does not shrink the app glyphs.
|
|
183
|
+
*/
|
|
184
|
+
export const APP_MARK_CROP_VIEWBOX = "173 197 629 629";
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* `projectv` (a brand mark, not an app) keeps a 687 x 687 frame, centred on `markBBox("projectv")`
|
|
188
|
+
* (x 172 to 858, y 377 to 672, centre 515 x 524.5), with no extra padding.
|
|
189
|
+
*/
|
|
190
|
+
export const PROJECTV_MARK_VIEWBOX = "171.5 181 687 687";
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Plain-mark viewBox per app. Always square. The five apps keep one 629 side (equal scale), and each origin is
|
|
194
|
+
* `markBBox(app)` centre minus 314.5 on both axes, so every glyph sits centred in its own frame. `projectv` uses
|
|
195
|
+
* its 687 frame, centre minus 343.5. Hardcoded; checked against `markBBox` in tests.
|
|
181
196
|
*/
|
|
182
197
|
export const APP_MARK_VIEWBOX: Record<AppName, string> = {
|
|
183
|
-
projectv:
|
|
184
|
-
vibot: "
|
|
185
|
-
vhub: "
|
|
186
|
-
vmem: "
|
|
187
|
-
verve: "
|
|
188
|
-
velth: "
|
|
198
|
+
projectv: PROJECTV_MARK_VIEWBOX,
|
|
199
|
+
vibot: "227.5 198.5 629 629",
|
|
200
|
+
vhub: "162.5 197.5 629 629",
|
|
201
|
+
vmem: "197.24772201231343 196.33100022273135 629 629",
|
|
202
|
+
verve: "197.5 210.9 629 629",
|
|
203
|
+
velth: "197.5 202.45 629 629",
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Start-aligned viewBox per app, for `Icon*` `align="start"`. Same side and same y as `APP_MARK_VIEWBOX`; x is
|
|
208
|
+
* `markBBox(app)` minX, so the glyph's left ink edge sits flush with the frame's left edge. Hardcoded; checked
|
|
209
|
+
* against `markBBox` in tests.
|
|
210
|
+
*/
|
|
211
|
+
export const APP_MARK_VIEWBOX_START: Record<AppName, string> = {
|
|
212
|
+
projectv: "172 181 687 687",
|
|
213
|
+
vibot: "295 198.5 629 629",
|
|
214
|
+
vhub: "186 197.5 629 629",
|
|
215
|
+
vmem: "255.5301217210191 196.33100022273135 629 629",
|
|
216
|
+
verve: "260.4 210.9 629 629",
|
|
217
|
+
velth: "273.9433593555699 202.45 629 629",
|
|
189
218
|
};
|
|
190
219
|
|
|
191
|
-
/** Width over height of a mark's
|
|
220
|
+
/** Width over height of a mark's viewBox. Always about 1, because the viewBoxes are square. Kept for API stability; do not use it for sizing. */
|
|
192
221
|
export function markAspect(app: AppName): number {
|
|
193
222
|
const [, , w = 1, h = 1] = APP_MARK_VIEWBOX[app].split(" ").map(Number);
|
|
194
223
|
return w / h;
|
|
@@ -205,7 +234,7 @@ function pathElements(app: AppName): string {
|
|
|
205
234
|
return APP_MARKS[app].paths.map((d) => `<path d="${d}"/>`).join("");
|
|
206
235
|
}
|
|
207
236
|
|
|
208
|
-
/** Glyph only
|
|
237
|
+
/** Glyph only on its equalised square viewBox, painted with `color` (default `currentColor`). */
|
|
209
238
|
export function appMarkSvg(app: AppName, color = "currentColor"): string {
|
|
210
239
|
return `<svg ${NS} viewBox="${APP_MARK_VIEWBOX[app]}" ${markPaintAttrs(app, color)}>${pathElements(app)}</svg>\n`;
|
|
211
240
|
}
|
|
@@ -11,9 +11,7 @@ export const V_PRO_APP_BENEFITS: readonly PricingPlanAppBenefit[] = [
|
|
|
11
11
|
{
|
|
12
12
|
app: "vibot",
|
|
13
13
|
items: [
|
|
14
|
-
"
|
|
15
|
-
"100 image gens / day",
|
|
16
|
-
"100 deep & 20 extreme searches / day",
|
|
14
|
+
"Higher AI limits/usage",
|
|
17
15
|
"Smarter AI for chats, documents & sub-agents",
|
|
18
16
|
],
|
|
19
17
|
},
|