@vvedantb/native-ui 0.17.2 → 0.18.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/dist/AlertDialog.jsx +123 -0
- package/dist/AmbientBackground.jsx +73 -0
- package/dist/ArtifactList.jsx +59 -0
- package/dist/Avatar.jsx +285 -0
- package/dist/Badge.jsx +154 -0
- package/dist/BottomSheetContainer.jsx +208 -0
- package/dist/BulkActionBar.jsx +717 -0
- package/dist/Button.jsx +344 -0
- package/dist/CaptureButton.jsx +104 -0
- package/dist/Card.jsx +371 -0
- package/dist/Checkbox.jsx +177 -0
- package/dist/Chip.jsx +79 -0
- package/dist/ColorSwatches.jsx +159 -0
- package/dist/ConfirmDialog.jsx +157 -0
- package/dist/DateTimeField.jsx +204 -0
- package/dist/Dialog.jsx +614 -0
- package/dist/DividedList.jsx +120 -0
- package/dist/DropdownMenu.jsx +849 -0
- package/dist/EmptyState.jsx +434 -0
- package/dist/ExpoWebRoot.jsx +134 -0
- package/dist/FloatingFAB.jsx +95 -0
- package/dist/FloatingSurface.jsx +226 -0
- package/dist/FloatingTabBar.jsx +403 -0
- package/dist/HeaderIconButton.jsx +53 -0
- package/dist/IconButton.jsx +157 -0
- package/dist/Input.jsx +96 -0
- package/dist/Label.jsx +96 -0
- package/dist/LabeledSwitchRow.jsx +170 -0
- package/dist/LiquidGlass.jsx +2 -0
- package/dist/ListRow.jsx +281 -0
- package/dist/LoadingState.jsx +205 -0
- package/dist/PageIndicator.jsx +128 -0
- package/dist/PageTitle.jsx +205 -0
- package/dist/Pager.jsx +105 -0
- package/dist/PasswordInput.jsx +120 -0
- package/dist/PillTabs.jsx +300 -0
- package/dist/PinnedBotTile.jsx +212 -0
- package/dist/Progress.jsx +147 -0
- package/dist/SafeAreaContainer.jsx +38 -0
- package/dist/ScreenContainer.jsx +117 -0
- package/dist/SearchInput.jsx +150 -0
- package/dist/SectionLabel.jsx +128 -0
- package/dist/Select.jsx +223 -0
- package/dist/Separator.jsx +95 -0
- package/dist/Sheet.jsx +343 -0
- package/dist/SheetRow.jsx +198 -0
- package/dist/Skeleton.jsx +311 -0
- package/dist/Spinner.jsx +195 -0
- package/dist/StackPageHeader.jsx +160 -0
- package/dist/StatGrid.jsx +74 -0
- package/dist/StatusDot.jsx +129 -0
- package/dist/SurfaceRow.jsx +143 -0
- package/dist/SwipeableRow.jsx +50 -0
- package/dist/Switch.jsx +130 -0
- package/dist/Tabs.jsx +385 -0
- package/dist/Textarea.jsx +103 -0
- package/dist/ThemeToggle.jsx +78 -0
- package/dist/Toast.jsx +396 -0
- package/dist/ai/activity-step-detail.jsx +179 -0
- package/dist/ai/activity-step-label.js +816 -0
- package/dist/ai/activity-step-types.js +14 -0
- package/dist/ai/activity-step.jsx +98 -0
- package/dist/ai/activity-tasks-utils.js +172 -0
- package/dist/ai/activity-timeline.js +47 -0
- package/dist/ai/attachments.jsx +258 -0
- package/dist/ai/card-button.jsx +188 -0
- package/dist/ai/chain-of-thought.jsx +459 -0
- package/dist/ai/chat-jump-rail.jsx +57 -0
- package/dist/ai/chat-text.js +44 -0
- package/dist/ai/chat-thread.jsx +135 -0
- package/dist/ai/choice-question.jsx +925 -0
- package/dist/ai/code-block.jsx +574 -0
- package/dist/ai/collapsible.jsx +275 -0
- package/dist/ai/conversation.jsx +723 -0
- package/dist/ai/file-chip.jsx +198 -0
- package/dist/ai/icon-button.jsx +179 -0
- package/dist/ai/index.js +37 -0
- package/dist/ai/message-action-sheet.jsx +408 -0
- package/dist/ai/message-quote.jsx +241 -0
- package/dist/ai/message.jsx +739 -0
- package/dist/ai/prompt-input-menu.jsx +365 -0
- package/dist/ai/prompt-input.jsx +626 -0
- package/dist/ai/reasoning.jsx +446 -0
- package/dist/ai/reply-quote-chip.jsx +278 -0
- package/dist/ai/response-text.jsx +130 -0
- package/dist/ai/shimmer.jsx +149 -0
- package/dist/ai/sources.jsx +260 -0
- package/dist/ai/subagent-cards.jsx +645 -0
- package/dist/ai/suggestion.jsx +186 -0
- package/dist/ai/tool-approval-card.jsx +359 -0
- package/dist/ai/trace.jsx +728 -0
- package/dist/ai/unified-diff.jsx +280 -0
- package/dist/ai/use-streaming-disclosure.js +70 -0
- package/dist/auth/AuthProviders.jsx +27 -0
- package/dist/auth/AuthScreen.jsx +292 -0
- package/dist/auth/GoogleSignInButton.jsx +188 -0
- package/dist/auth/SecondFactorScreen.jsx +133 -0
- package/dist/auth/SignInScreen.jsx +482 -0
- package/dist/auth/authErrors.js +131 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/totp.js +378 -0
- package/dist/blur.js +36 -0
- package/dist/brand/AppIcons.jsx +118 -0
- package/dist/brand/AppMark.jsx +128 -0
- package/dist/brand/AppWordmark.jsx +138 -0
- package/dist/brand/GoogleMark.jsx +71 -0
- package/dist/brand/ProviderIcon.jsx +192 -0
- package/dist/brand/familyApps.js +33 -0
- package/dist/brand/index.js +11 -0
- package/dist/brand/svg.js +252 -0
- package/dist/brand/vProAppBenefits.js +19 -0
- package/dist/cn.js +5 -0
- package/dist/colors.js +15 -0
- package/dist/configureTheme.js +72 -0
- package/dist/controlStyles.js +520 -0
- package/dist/definiteSize.js +12 -0
- package/dist/dialogLayout.js +18 -0
- package/dist/entries/ai.js +4 -0
- package/dist/entries/ambient.js +3 -0
- package/dist/entries/auth.js +5 -0
- package/dist/entries/bottom-sheet.js +2 -0
- package/dist/entries/brand.js +2 -0
- package/dist/entries/button.js +2 -0
- package/dist/entries/date-time.js +3 -0
- package/dist/entries/expo-router.js +4 -0
- package/dist/entries/expo-web-root.js +3 -0
- package/dist/entries/floating.js +7 -0
- package/dist/entries/gesture-handler.js +4 -0
- package/dist/entries/keyboard-controller.js +4 -0
- package/dist/entries/layout.js +16 -0
- package/dist/entries/markdown.js +4 -0
- package/dist/entries/marketing.js +3 -0
- package/dist/entries/page-title.js +7 -0
- package/dist/entries/password-input.js +3 -0
- package/dist/entries/primitives.js +57 -0
- package/dist/entries/search-input.js +3 -0
- package/dist/entries/tab-bar.js +4 -0
- package/dist/entries/theme.js +7 -0
- package/dist/entries/toast.js +5 -0
- package/dist/entries/video.js +3 -0
- package/dist/entries/webview.js +4 -0
- package/dist/examples/AiChatGallery.jsx +509 -0
- package/dist/examples/ParityGallery.jsx +1307 -0
- package/dist/floating.js +62 -0
- package/dist/glassBlur.jsx +145 -0
- package/dist/gradient.js +17 -0
- package/dist/haptics.js +44 -0
- package/dist/highlight.js +382 -0
- package/dist/index.js +85 -0
- package/dist/initials.js +4 -0
- package/dist/loadingGrid.js +81 -0
- package/dist/markdown/Markdown.jsx +515 -0
- package/dist/markdown/MarkdownTable.jsx +443 -0
- package/dist/markdown/tableText.js +68 -0
- package/dist/marketing/PricingModal.jsx +608 -0
- package/dist/marketing/UpgradeToProCard.jsx +164 -0
- package/dist/marketing/pricing.js +34 -0
- package/dist/media/ImageGallery.jsx +580 -0
- package/dist/media/MediaCard.jsx +162 -0
- package/dist/media/imageGrid.js +54 -0
- package/dist/motion.js +33 -0
- package/dist/pagerSwipe.js +104 -0
- package/dist/palette.js +104 -0
- package/dist/primitives/button.jsx +127 -0
- package/dist/primitives/card.jsx +249 -0
- package/dist/primitives/icon.jsx +37 -0
- package/dist/primitives/input.jsx +56 -0
- package/dist/primitives/keyboard-controller.jsx +207 -0
- package/dist/primitives/keyboard-parts.jsx +75 -0
- package/dist/primitives/native-only-animated-view.jsx +68 -0
- package/dist/primitives/overlay.jsx +391 -0
- package/dist/primitives/pager-gesture.jsx +131 -0
- package/dist/primitives/select-host.jsx +103 -0
- package/dist/primitives/select.jsx +555 -0
- package/dist/primitives/sheet-drag.jsx +420 -0
- package/dist/primitives/sheet-gesture.jsx +219 -0
- package/dist/primitives/swipe-row-gesture.jsx +341 -0
- package/dist/primitives/switch.jsx +105 -0
- package/dist/primitives/text.jsx +145 -0
- package/dist/primitives/toast-drag-gesture.jsx +94 -0
- package/dist/primitives/use-controllable-state.js +40 -0
- package/dist/primitives/web-click-guard.js +69 -0
- package/dist/push.js +166 -0
- package/dist/relativeTime.js +70 -0
- package/dist/router/RouterStackPageHeader.jsx +53 -0
- package/dist/selectA11y.js +32 -0
- package/dist/settings/MoreFromProjectV.jsx +168 -0
- package/dist/settings/SettingsEmptyState.jsx +102 -0
- package/dist/settings/SettingsField.jsx +49 -0
- package/dist/settings/SettingsSection.jsx +101 -0
- package/dist/settings/SettingsStack.jsx +17 -0
- package/dist/settings/SettingsToggleRow.jsx +163 -0
- package/dist/settings/projectVMobileApps.js +126 -0
- package/dist/settings/relaxedSizeStyle.js +11 -0
- package/dist/sheetDrag.js +76 -0
- package/dist/svgA11y.js +46 -0
- package/dist/swipeRow.js +161 -0
- package/dist/tabBarRoutes.js +41 -0
- package/dist/tabIndicator.js +139 -0
- package/dist/tailwind-preset.cjs +255 -0
- package/dist/tailwind-preset.d.cts +55 -0
- package/dist/theme.jsx +62 -0
- package/dist/toastChrome.js +110 -0
- package/dist/toastDrag.js +51 -0
- package/dist/toastStore.js +54 -0
- package/dist/tokens.js +70 -0
- package/dist/typography.js +40 -0
- package/dist/useReduceMotion.js +32 -0
- package/dist/useReduceTransparency.js +27 -0
- package/dist/useScheme.js +15 -0
- package/dist/video/InlineVideo.jsx +115 -0
- package/dist/webview/HtmlView.jsx +169 -0
- package/dist/webview/HtmlView.web.jsx +63 -0
- package/dist/webview/htmlView.js +43 -0
- package/package.json +70 -33
- package/src/DropdownMenu.tsx +28 -16
- package/src/FloatingTabBar.tsx +78 -41
- package/src/ai/conversation.tsx +12 -8
- package/src/glassBlur.tsx +47 -22
- package/src/primitives/swipe-row-gesture.tsx +11 -2
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Geometry and raw SVG strings for the family app marks. No imports, so the
|
|
2
|
+
// asset script can load this file directly with Node.
|
|
3
|
+
|
|
4
|
+
/** Every mark. `eva` and `bee` are marks and icons only: they are not family apps, so `FAMILY_APPS` leaves them out. */
|
|
5
|
+
export const APP_NAMES = ["projectv", "vibot", "vhub", "vmem", "verve", "velth", "eva", "bee"];
|
|
6
|
+
|
|
7
|
+
/** `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. */
|
|
8
|
+
|
|
9
|
+
export const MARK_VIEWBOX = "0 0 1024 1024";
|
|
10
|
+
export const MARK_STROKE_WIDTH = 50;
|
|
11
|
+
export const TILE_RADIUS = 224;
|
|
12
|
+
/** Stroke width of a mark on the 1024 grid. */
|
|
13
|
+
export function markStrokeWidth(app) {
|
|
14
|
+
return APP_MARKS[app].strokeWidth ?? MARK_STROKE_WIDTH;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Line cap of a mark. */
|
|
18
|
+
export function markLinecap(app) {
|
|
19
|
+
return APP_MARKS[app].linecap ?? "round";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Glyphs sized by one rule: longest side = 512 * min(1.2, aspect^0.25), centred halfway between
|
|
24
|
+
* the bounding-box centre and the centre of mass. `verve` and `velth` are the final vectors.
|
|
25
|
+
* `vibot`, `vhub`, `vmem` and `projectv` are traced from the approved 1024px renders. `eva` (option A,
|
|
26
|
+
* a filled four-point star) and `bee` (option D, an orb with eyes, stripes and antennae) are the final
|
|
27
|
+
* vectors from their design sheet, as drawn there.
|
|
28
|
+
*/
|
|
29
|
+
export const APP_MARKS = {
|
|
30
|
+
projectv: {
|
|
31
|
+
kind: "fill",
|
|
32
|
+
paths: ["M172 398L260 397L418 558L580 377L858 378L824 415L604 415L452 598L466 611L622 433L808 433L773 471L658 471L491 671L442 672Z"]
|
|
33
|
+
},
|
|
34
|
+
vibot: {
|
|
35
|
+
kind: "fill",
|
|
36
|
+
paths: ["M295 314L396 314L396 574C520 540 620 440 655 314L711 314C680 470 560 590 396 627L390 627L390 651L396 651C560 610 700 480 734 314L789 314C740 540 560 712 295 712Z"]
|
|
37
|
+
},
|
|
38
|
+
vhub: {
|
|
39
|
+
kind: "stroke",
|
|
40
|
+
paths: ["M211 512L743 512", "M415 512C500 512 540 363 743 363", "M415 512C500 512 540 661 743 661"]
|
|
41
|
+
},
|
|
42
|
+
vmem: {
|
|
43
|
+
kind: "stroke",
|
|
44
|
+
strokeWidth: 58,
|
|
45
|
+
linecap: "butt",
|
|
46
|
+
paths: ["M693.2 379.5A227.25 227.25 0 0 1 581.0 732.7", "M442.5 732.7A227.25 227.25 0 0 1 330.9 378.7", "M397.3 319.9A227.25 227.25 0 0 1 627.1 320.4"]
|
|
47
|
+
},
|
|
48
|
+
verve: {
|
|
49
|
+
kind: "stroke",
|
|
50
|
+
paths: ["M285.4 344.1Q428.6 344.1 512 552.6Q595.4 344.1 738.6 344.1", "M285.4 344.1L285.4 579.8Q428.6 579.8 512 706.7Q595.4 579.8 738.6 579.8L738.6 344.1"]
|
|
51
|
+
},
|
|
52
|
+
velth: {
|
|
53
|
+
kind: "stroke",
|
|
54
|
+
paths: ["M512 732.3C379.8 652.1 289.7 471.9 299.7 301.6C419.9 371.7 500 552 512 732.3Z", "M512 732.3C644.2 652.1 734.3 471.9 724.3 301.6C604.1 371.7 524 552 512 732.3Z"]
|
|
55
|
+
},
|
|
56
|
+
eva: {
|
|
57
|
+
kind: "fill",
|
|
58
|
+
paths: ["M242.9 512Q485.1 485.1 512 278.8Q538.9 485.1 781 512Q538.9 538.9 512 745.1Q485.1 538.9 242.9 512Z"]
|
|
59
|
+
},
|
|
60
|
+
bee: {
|
|
61
|
+
kind: "stroke",
|
|
62
|
+
paths: ["M304 530.7A208.1 208.1 0 1 1 720.1 530.7A208.1 208.1 0 1 1 304 530.7", "M447.5 414.2L447.5 445.4", "M576.5 414.2L576.5 445.4", "M306.3 561.9L717.7 561.9", "M344 653.4L680 653.4", "M468.3 341.4Q455.8 291.4 420.5 260.2", "M555.7 341.4Q568.2 291.4 603.5 260.2"]
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
/** Roots in (0, 1) of the derivative of a Bezier with 1D control values `v` (quadratic or cubic). */
|
|
66
|
+
function bezierExtrema(v) {
|
|
67
|
+
const roots = [];
|
|
68
|
+
if (v.length === 3) {
|
|
69
|
+
const d = v[0] - 2 * v[1] + v[2];
|
|
70
|
+
if (d !== 0) roots.push((v[0] - v[1]) / d);
|
|
71
|
+
} else {
|
|
72
|
+
const a = -v[0] + 3 * v[1] - 3 * v[2] + v[3];
|
|
73
|
+
const b = 2 * (v[0] - 2 * v[1] + v[2]);
|
|
74
|
+
const c = v[1] - v[0];
|
|
75
|
+
if (Math.abs(a) < 1e-12) {
|
|
76
|
+
if (b !== 0) roots.push(-c / b);
|
|
77
|
+
} else {
|
|
78
|
+
const disc = b * b - 4 * a * c;
|
|
79
|
+
if (disc >= 0) roots.push((-b + Math.sqrt(disc)) / (2 * a), (-b - Math.sqrt(disc)) / (2 * a));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return roots.filter(t => t > 0 && t < 1);
|
|
83
|
+
}
|
|
84
|
+
function bezierAt(v, t) {
|
|
85
|
+
const u = 1 - t;
|
|
86
|
+
const [p0, p1, p2, p3] = v;
|
|
87
|
+
return v.length === 3 ? u * u * p0 + 2 * u * t * p1 + t * t * p2 : u ** 3 * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t ** 3 * p3;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Extreme points of an SVG elliptical arc (endpoint form, no rotation), including both ends. */
|
|
91
|
+
function arcPoints(from, [rx0, ry0,, large, sweep, x, y]) {
|
|
92
|
+
const [x0, y0] = from;
|
|
93
|
+
let rx = Math.abs(rx0);
|
|
94
|
+
let ry = Math.abs(ry0);
|
|
95
|
+
const dx = (x0 - x) / 2;
|
|
96
|
+
const dy = (y0 - y) / 2;
|
|
97
|
+
const lambda = dx * dx / (rx * rx) + dy * dy / (ry * ry);
|
|
98
|
+
if (lambda > 1) {
|
|
99
|
+
rx *= Math.sqrt(lambda);
|
|
100
|
+
ry *= Math.sqrt(lambda);
|
|
101
|
+
}
|
|
102
|
+
const num = rx * rx * ry * ry - rx * rx * dy * dy - ry * ry * dx * dx;
|
|
103
|
+
const den = rx * rx * dy * dy + ry * ry * dx * dx;
|
|
104
|
+
const k = (large === sweep ? -1 : 1) * Math.sqrt(Math.max(0, num / den));
|
|
105
|
+
const cx = k * (rx * dy / ry) + (x0 + x) / 2;
|
|
106
|
+
const cy = k * (-(ry * dx) / rx) + (y0 + y) / 2;
|
|
107
|
+
const a0 = Math.atan2((y0 - cy) / ry, (x0 - cx) / rx);
|
|
108
|
+
let delta = Math.atan2((y - cy) / ry, (x - cx) / rx) - a0;
|
|
109
|
+
if (sweep && delta < 0) delta += 2 * Math.PI;
|
|
110
|
+
if (!sweep && delta > 0) delta -= 2 * Math.PI;
|
|
111
|
+
const points = [from, [x, y]];
|
|
112
|
+
for (let q = -6; q <= 6; q++) {
|
|
113
|
+
const a = q * Math.PI / 2;
|
|
114
|
+
const t = (a - a0) / delta;
|
|
115
|
+
if (t > 0 && t < 1) points.push([cx + rx * Math.cos(a), cy + ry * Math.sin(a)]);
|
|
116
|
+
}
|
|
117
|
+
return points;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Exact bounding box of absolute `M`, `L`, `Q`, `C` and `A` path data (the only commands the marks use). Returns [minX, minY, maxX, maxY]. */
|
|
121
|
+
export function pathBBox(d) {
|
|
122
|
+
const tokens = d.match(/[MLQCA]|-?\d*\.?\d+(?:e-?\d+)?/g) ?? [];
|
|
123
|
+
const points = [];
|
|
124
|
+
let cmd = "";
|
|
125
|
+
let cur = [0, 0];
|
|
126
|
+
const argc = {
|
|
127
|
+
M: 2,
|
|
128
|
+
L: 2,
|
|
129
|
+
Q: 4,
|
|
130
|
+
C: 6,
|
|
131
|
+
A: 7
|
|
132
|
+
};
|
|
133
|
+
for (let i = 0; i < tokens.length;) {
|
|
134
|
+
if (/[A-Z]/.test(tokens[i])) cmd = tokens[i++];
|
|
135
|
+
const n = argc[cmd];
|
|
136
|
+
if (!n) throw new Error(`Unsupported path command: ${cmd}`);
|
|
137
|
+
const a = tokens.slice(i, i + n).map(Number);
|
|
138
|
+
i += n;
|
|
139
|
+
const end = [a[n - 2], a[n - 1]];
|
|
140
|
+
if (cmd === "Q" || cmd === "C") {
|
|
141
|
+
const xs = [cur[0], ...a.filter((_, j) => j % 2 === 0)];
|
|
142
|
+
const ys = [cur[1], ...a.filter((_, j) => j % 2 === 1)];
|
|
143
|
+
for (const t of new Set([...bezierExtrema(xs), ...bezierExtrema(ys)])) points.push([bezierAt(xs, t), bezierAt(ys, t)]);
|
|
144
|
+
} else if (cmd === "A") {
|
|
145
|
+
points.push(...arcPoints(cur, a));
|
|
146
|
+
}
|
|
147
|
+
points.push(end);
|
|
148
|
+
cur = end;
|
|
149
|
+
}
|
|
150
|
+
return [Math.min(...points.map(p => p[0])), Math.min(...points.map(p => p[1])), Math.max(...points.map(p => p[0])), Math.max(...points.map(p => p[1]))];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Tight box of a mark: union of its paths, grown by half the stroke width for stroke marks. Returns [minX, minY, maxX, maxY]. */
|
|
154
|
+
export function markBBox(app) {
|
|
155
|
+
const {
|
|
156
|
+
kind,
|
|
157
|
+
paths
|
|
158
|
+
} = APP_MARKS[app];
|
|
159
|
+
const boxes = paths.map(pathBBox);
|
|
160
|
+
const pad = kind === "stroke" ? markStrokeWidth(app) / 2 : 0;
|
|
161
|
+
return [Math.min(...boxes.map(b => b[0])) - pad, Math.min(...boxes.map(b => b[1])) - pad, Math.max(...boxes.map(b => b[2])) + pad, Math.max(...boxes.map(b => b[3])) + pad];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Frame size for the five app glyphs (`vibot`, `vhub`, `vmem`, `verve`, `velth`) in the plain logo (`variant="mark"`,
|
|
166
|
+
* `appMarkSvg`, `Icon*`): a 629 x 629 square, the union of their `markBBox` results on the 1024 tile grid
|
|
167
|
+
* (x 186 to 789, y 259.96 to 761.7) at side max(width, height) x 1.04 (about 4% padding), rounded outward.
|
|
168
|
+
* All five use this side, so glyph scale stays equal. Only the size is shared: each app has its own origin in
|
|
169
|
+
* `APP_MARK_VIEWBOX`. `projectv` is left out so its wide brand mark does not shrink the app glyphs.
|
|
170
|
+
* Historical: this union covers those five only. `eva` and `bee` reuse the 629 side but are not part of it.
|
|
171
|
+
*/
|
|
172
|
+
export const APP_MARK_CROP_VIEWBOX = "173 197 629 629";
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* `projectv` (a brand mark, not an app) keeps a 687 x 687 frame, centred on `markBBox("projectv")`
|
|
176
|
+
* (x 172 to 858, y 377 to 672, centre 515 x 524.5), with no extra padding.
|
|
177
|
+
*/
|
|
178
|
+
export const PROJECTV_MARK_VIEWBOX = "171.5 181 687 687";
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Plain-mark viewBox per app. Always square. Every mark except `projectv` keeps one 629 side (equal scale), and each
|
|
182
|
+
* origin is `markBBox(app)` centre minus 314.5 on both axes, so every glyph sits centred in its own frame. `projectv`
|
|
183
|
+
* uses its 687 frame, centre minus 343.5. Hardcoded; checked against `markBBox` in tests.
|
|
184
|
+
*/
|
|
185
|
+
export const APP_MARK_VIEWBOX = {
|
|
186
|
+
projectv: PROJECTV_MARK_VIEWBOX,
|
|
187
|
+
vibot: "227.5 198.5 629 629",
|
|
188
|
+
vhub: "162.5 197.5 629 629",
|
|
189
|
+
vmem: "197.24772201231343 196.33100022273135 629 629",
|
|
190
|
+
verve: "197.5 210.9 629 629",
|
|
191
|
+
velth: "197.5 202.45 629 629",
|
|
192
|
+
eva: "197.45 197.45 629 629",
|
|
193
|
+
bee: "197.55 187.2807619340906 629 629"
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Start-aligned viewBox per app, for `Icon*` `align="start"`. Same side and same y as `APP_MARK_VIEWBOX`; x is
|
|
198
|
+
* `markBBox(app)` minX, so the glyph's left ink edge sits flush with the frame's left edge. Hardcoded; checked
|
|
199
|
+
* against `markBBox` in tests.
|
|
200
|
+
*/
|
|
201
|
+
export const APP_MARK_VIEWBOX_START = {
|
|
202
|
+
projectv: "172 181 687 687",
|
|
203
|
+
vibot: "295 198.5 629 629",
|
|
204
|
+
vhub: "186 197.5 629 629",
|
|
205
|
+
vmem: "255.5301217210191 196.33100022273135 629 629",
|
|
206
|
+
verve: "260.4 210.9 629 629",
|
|
207
|
+
velth: "273.9433593555699 202.45 629 629",
|
|
208
|
+
eva: "242.9 197.45 629 629",
|
|
209
|
+
bee: "278.94999999999993 187.2807619340906 629 629"
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/** 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. */
|
|
213
|
+
export function markAspect(app) {
|
|
214
|
+
const [,, w = 1, h = 1] = APP_MARK_VIEWBOX[app].split(" ").map(Number);
|
|
215
|
+
return w / h;
|
|
216
|
+
}
|
|
217
|
+
const NS = 'xmlns="http://www.w3.org/2000/svg"';
|
|
218
|
+
|
|
219
|
+
/** Attributes that paint the glyph in `color`. */
|
|
220
|
+
export function markPaintAttrs(app, color) {
|
|
221
|
+
return APP_MARKS[app].kind === "fill" ? `fill="${color}"` : `fill="none" stroke="${color}" stroke-width="${markStrokeWidth(app)}" stroke-linecap="${markLinecap(app)}" stroke-linejoin="round"`;
|
|
222
|
+
}
|
|
223
|
+
function pathElements(app) {
|
|
224
|
+
return APP_MARKS[app].paths.map(d => `<path d="${d}"/>`).join("");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Glyph only on its equalised square viewBox, painted with `color` (default `currentColor`). */
|
|
228
|
+
export function appMarkSvg(app, color = "currentColor") {
|
|
229
|
+
return `<svg ${NS} viewBox="${APP_MARK_VIEWBOX[app]}" ${markPaintAttrs(app, color)}>${pathElements(app)}</svg>\n`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** Tile with a glyph. `radius` 0 gives a full-bleed square (apple-touch, maskable). */
|
|
233
|
+
export function appTileSvg(app, tone = "dark", radius = TILE_RADIUS) {
|
|
234
|
+
const [bg, fg] = tone === "dark" ? ["#000", "#fff"] : ["#fff", "#000"];
|
|
235
|
+
const rx = radius > 0 ? ` rx="${radius}"` : "";
|
|
236
|
+
return `<svg ${NS} viewBox="${MARK_VIEWBOX}"><rect width="1024" height="1024"${rx} fill="${bg}"/><g ${markPaintAttrs(app, fg)}>${pathElements(app)}</g></svg>\n`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Android adaptive-icon layer: 432 canvas, glyph scaled into the 288 inner square. */
|
|
240
|
+
export function appAdaptiveSvg(app, color) {
|
|
241
|
+
const scale = 288 / 1024;
|
|
242
|
+
return `<svg ${NS} viewBox="0 0 432 432"><g transform="translate(216 216) scale(${scale}) translate(-512 -512)" ${markPaintAttrs(app, color)}>${pathElements(app)}</g></svg>\n`;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Chrome extension 128px icon: 96px tile plus 16px transparent padding. */
|
|
246
|
+
export function appExtension128Svg(app) {
|
|
247
|
+
const inner = appTileSvg(app).replace(`<svg ${NS} viewBox="${MARK_VIEWBOX}">`, `<svg ${NS} x="16" y="16" width="96" height="96" viewBox="${MARK_VIEWBOX}">`);
|
|
248
|
+
return `<svg ${NS} viewBox="0 0 128 128">${inner.trim()}</svg>\n`;
|
|
249
|
+
}
|
|
250
|
+
export const APP_MARK_SVG = Object.fromEntries(APP_NAMES.map(app => [app, appMarkSvg(app)]));
|
|
251
|
+
export const APP_TILE_SVG = Object.fromEntries(APP_NAMES.map(app => [app, appTileSvg(app)]));
|
|
252
|
+
export const APP_TILE_LIGHT_SVG = Object.fromEntries(APP_NAMES.map(app => [app, appTileSvg(app, "light")]));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Benefits for one app, shown under that app's icon and name. */
|
|
2
|
+
|
|
3
|
+
/** Approved per-app copy for V Pro, in display order. */
|
|
4
|
+
export const V_PRO_APP_BENEFITS = [{
|
|
5
|
+
app: "vibot",
|
|
6
|
+
items: ["Higher AI limits/usage", "Smarter AI for chats, documents & sub-agents"]
|
|
7
|
+
}, {
|
|
8
|
+
app: "vmem",
|
|
9
|
+
items: ["Unlimited memories", "Higher AI search & connected-tool limits"]
|
|
10
|
+
}, {
|
|
11
|
+
app: "vhub",
|
|
12
|
+
items: ["Unlimited scripts", "More connections, secrets & API keys"]
|
|
13
|
+
}, {
|
|
14
|
+
app: "velth",
|
|
15
|
+
items: ["Unlimited camera scans", "Smarter AI health insights"]
|
|
16
|
+
}, {
|
|
17
|
+
app: "verve",
|
|
18
|
+
items: ["Page version history", "Higher AI rewrite & summary limits"]
|
|
19
|
+
}];
|
package/dist/cn.js
ADDED
package/dist/colors.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { tokens } from "./tokens";
|
|
2
|
+
export const NEUTRAL_100 = "#f5f5f5";
|
|
3
|
+
export const NEUTRAL_500 = tokens.color.muted.light;
|
|
4
|
+
export const NEUTRAL_900 = "#171717";
|
|
5
|
+
export const PINK_50 = "#fdf2f8";
|
|
6
|
+
export const PINK_100 = "#fce7f3";
|
|
7
|
+
export const PINK_600 = "#db2777";
|
|
8
|
+
export const PINK_700 = "#be185d";
|
|
9
|
+
export const Colors = {
|
|
10
|
+
white: tokens.color.white,
|
|
11
|
+
black: tokens.color.black,
|
|
12
|
+
neutral: {
|
|
13
|
+
800: "#262626"
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { palette } from "./palette";
|
|
2
|
+
import { tokens } from "./tokens";
|
|
3
|
+
import { fontFamily } from "./typography";
|
|
4
|
+
|
|
5
|
+
/** `tokens` and `palette` value types with the literal hex widened to `string` and `readonly` dropped. */
|
|
6
|
+
|
|
7
|
+
/** The `tokens.color` shape: each key a `{ light, dark }` pair, except `white` and `black`. */
|
|
8
|
+
|
|
9
|
+
/** The `palette` shape: each key a `{ light, dark }` pair, except `destructive`. */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Copies each given key onto `target`. A `{ light, dark }` pair is copied into
|
|
13
|
+
* the existing pair object, so values that hold the pair (`floatingFill`,
|
|
14
|
+
* `floatingHairline`, `floatingSolidFill`) follow it.
|
|
15
|
+
*/
|
|
16
|
+
function assignValues(target, source) {
|
|
17
|
+
for (const [key, value] of Object.entries(source)) {
|
|
18
|
+
if (value === undefined) continue;
|
|
19
|
+
const current = target[key];
|
|
20
|
+
if (typeof current === "object" && typeof value === "object") Object.assign(current, value);else Object.assign(target, {
|
|
21
|
+
[key]: value
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Bumped by each `configureTheme` call; `useScheme` redraws on it. */
|
|
27
|
+
let themeVersion = 0;
|
|
28
|
+
const themeListeners = new Set();
|
|
29
|
+
|
|
30
|
+
/** Calls `listener` after each `configureTheme`. Returns the unsubscribe. */
|
|
31
|
+
export function subscribeTheme(listener) {
|
|
32
|
+
themeListeners.add(listener);
|
|
33
|
+
return () => {
|
|
34
|
+
themeListeners.delete(listener);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The number of `configureTheme` calls so far, a snapshot for `useSyncExternalStore`. */
|
|
39
|
+
export function getThemeVersion() {
|
|
40
|
+
return themeVersion;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sets the app's own colours and fonts. It writes into the shared
|
|
45
|
+
* `tokens.color`, `palette` and `fontFamily` objects, which every component
|
|
46
|
+
* reads at render. Call it once at app start, before the first render (for
|
|
47
|
+
* example at the top of the root `_layout.tsx`, outside the component). A
|
|
48
|
+
* later call (for example a second dark palette the user picks) redraws the
|
|
49
|
+
* mounted components under `NativeUiProvider` that read the scheme (`useScheme`); app code that copies
|
|
50
|
+
* values out, or memoises on the scheme alone, must redraw on its own. Each
|
|
51
|
+
* pair gives both schemes:
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* configureTheme({
|
|
55
|
+
* color: { background: { light: "#f4f5f6", dark: "#020202" } },
|
|
56
|
+
* palette: { primary: { light: "#09090b", dark: "#fafafa" } },
|
|
57
|
+
* font: { regular: "Inter_400Regular", semibold: "Inter_600SemiBold" },
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* Only the JS values change. NativeWind classes keep the app's Tailwind theme
|
|
62
|
+
* (`tailwind-preset` reads the package values from source; pass the same
|
|
63
|
+
* family names to `nativeUiPreset({ font })`), and constants copied out before
|
|
64
|
+
* the call (`NEUTRAL_500`) keep the package value. The app loads the font files.
|
|
65
|
+
*/
|
|
66
|
+
export function configureTheme(config) {
|
|
67
|
+
if (config.color) assignValues(tokens.color, config.color);
|
|
68
|
+
if (config.palette) assignValues(palette, config.palette);
|
|
69
|
+
if (config.font) assignValues(fontFamily, config.font);
|
|
70
|
+
themeVersion += 1;
|
|
71
|
+
for (const listener of themeListeners) listener();
|
|
72
|
+
}
|