@waveinno/ui 0.0.0-stage → 0.1.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/CHANGELOG.md +39 -0
- package/LICENSE +5 -0
- package/README.md +64 -2
- package/dist/brand/waveinno-logo.svg +1 -0
- package/dist/components/brand/index.d.ts +3 -0
- package/dist/components/brand/index.js +1 -0
- package/dist/components/brand/logo.d.ts +89 -0
- package/dist/components/brand/logo.js +1 -0
- package/dist/components/brand/waveinno-logo.d.ts +52 -0
- package/dist/components/brand/waveinno-logo.js +1 -0
- package/dist/components/charts/bar-chart.d.ts +20 -0
- package/dist/components/charts/bar-chart.js +1 -0
- package/dist/components/charts/bar-list.d.ts +27 -0
- package/dist/components/charts/bar-list.js +1 -0
- package/dist/components/charts/chart-card.d.ts +32 -0
- package/dist/components/charts/chart-card.js +1 -0
- package/dist/components/charts/donut-chart.d.ts +29 -0
- package/dist/components/charts/donut-chart.js +1 -0
- package/dist/components/charts/gauge-chart.d.ts +21 -0
- package/dist/components/charts/gauge-chart.js +1 -0
- package/dist/components/charts/heatmap.d.ts +23 -0
- package/dist/components/charts/heatmap.js +1 -0
- package/dist/components/charts/index.d.ts +10 -0
- package/dist/components/charts/index.js +1 -0
- package/dist/components/charts/line-chart.d.ts +24 -0
- package/dist/components/charts/line-chart.js +1 -0
- package/dist/components/charts/palette.d.ts +39 -0
- package/dist/components/charts/palette.js +1 -0
- package/dist/components/charts/trend-chart.d.ts +22 -0
- package/dist/components/charts/trend-chart.js +1 -0
- package/dist/components/patterns/activity-feed.d.ts +28 -0
- package/dist/components/patterns/activity-feed.js +1 -0
- package/dist/components/patterns/data-table-cells.d.ts +39 -0
- package/dist/components/patterns/data-table-cells.js +1 -0
- package/dist/components/patterns/data-table-edit.d.ts +56 -0
- package/dist/components/patterns/data-table-edit.js +1 -0
- package/dist/components/patterns/data-table-filters.d.ts +84 -0
- package/dist/components/patterns/data-table-filters.js +1 -0
- package/dist/components/patterns/data-table.d.ts +76 -0
- package/dist/components/patterns/data-table.js +2 -0
- package/dist/components/patterns/index.d.ts +16 -0
- package/dist/components/patterns/index.js +1 -0
- package/dist/components/patterns/kanban.d.ts +28 -0
- package/dist/components/patterns/kanban.js +1 -0
- package/dist/components/patterns/kpi-card.d.ts +22 -0
- package/dist/components/patterns/kpi-card.js +1 -0
- package/dist/components/patterns/money.d.ts +28 -0
- package/dist/components/patterns/money.js +1 -0
- package/dist/components/patterns/page-header.d.ts +38 -0
- package/dist/components/patterns/page-header.js +1 -0
- package/dist/components/patterns/page-hero.d.ts +50 -0
- package/dist/components/patterns/page-hero.js +1 -0
- package/dist/components/patterns/page-shell.d.ts +27 -0
- package/dist/components/patterns/page-shell.js +1 -0
- package/dist/components/patterns/stat-card.d.ts +56 -0
- package/dist/components/patterns/stat-card.js +1 -0
- package/dist/components/patterns/states.d.ts +27 -0
- package/dist/components/patterns/states.js +1 -0
- package/dist/components/patterns/timeline.d.ts +100 -0
- package/dist/components/patterns/timeline.js +1 -0
- package/dist/components/ui/avatar.d.ts +37 -0
- package/dist/components/ui/avatar.js +1 -0
- package/dist/components/ui/badge.d.ts +41 -0
- package/dist/components/ui/badge.js +1 -0
- package/dist/components/ui/button.d.ts +25 -0
- package/dist/components/ui/button.js +1 -0
- package/dist/components/ui/calendar.d.ts +42 -0
- package/dist/components/ui/calendar.js +1 -0
- package/dist/components/ui/card.d.ts +11 -0
- package/dist/components/ui/card.js +1 -0
- package/dist/components/ui/checkbox.d.ts +3 -0
- package/dist/components/ui/checkbox.js +1 -0
- package/dist/components/ui/combobox.d.ts +47 -0
- package/dist/components/ui/combobox.js +1 -0
- package/dist/components/ui/confirm-dialog.d.ts +34 -0
- package/dist/components/ui/confirm-dialog.js +1 -0
- package/dist/components/ui/date-picker.d.ts +80 -0
- package/dist/components/ui/date-picker.js +1 -0
- package/dist/components/ui/dialog.d.ts +54 -0
- package/dist/components/ui/dialog.js +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +44 -0
- package/dist/components/ui/dropdown-menu.js +1 -0
- package/dist/components/ui/form-field.d.ts +27 -0
- package/dist/components/ui/form-field.js +1 -0
- package/dist/components/ui/index.d.ts +26 -0
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/input.d.ts +21 -0
- package/dist/components/ui/input.js +1 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.js +1 -0
- package/dist/components/ui/popover.d.ts +22 -0
- package/dist/components/ui/popover.js +1 -0
- package/dist/components/ui/progress.d.ts +43 -0
- package/dist/components/ui/progress.js +1 -0
- package/dist/components/ui/segmented.d.ts +42 -0
- package/dist/components/ui/segmented.js +1 -0
- package/dist/components/ui/select.d.ts +10 -0
- package/dist/components/ui/select.js +1 -0
- package/dist/components/ui/separator.d.ts +3 -0
- package/dist/components/ui/separator.js +1 -0
- package/dist/components/ui/sheet.d.ts +19 -0
- package/dist/components/ui/sheet.js +1 -0
- package/dist/components/ui/skeleton.d.ts +10 -0
- package/dist/components/ui/skeleton.js +1 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/switch.js +1 -0
- package/dist/components/ui/tabs.d.ts +19 -0
- package/dist/components/ui/tabs.js +1 -0
- package/dist/components/ui/time-picker.d.ts +52 -0
- package/dist/components/ui/time-picker.js +1 -0
- package/dist/components/ui/tooltip.d.ts +13 -0
- package/dist/components/ui/tooltip.js +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/use-hotkey.d.ts +16 -0
- package/dist/hooks/use-hotkey.js +1 -0
- package/dist/hooks/use-media-query.d.ts +4 -0
- package/dist/hooks/use-media-query.js +1 -0
- package/dist/hooks/use-mounted.d.ts +2 -0
- package/dist/hooks/use-mounted.js +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1 -0
- package/dist/lib/boot-script.d.ts +15 -0
- package/dist/lib/boot-script.js +12 -0
- package/dist/lib/currency.d.ts +55 -0
- package/dist/lib/currency.js +1 -0
- package/dist/lib/format.d.ts +28 -0
- package/dist/lib/format.js +1 -0
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.js +1 -0
- package/dist/shell/app-shell.d.ts +18 -0
- package/dist/shell/app-shell.js +1 -0
- package/dist/shell/app-switcher.d.ts +9 -0
- package/dist/shell/app-switcher.js +1 -0
- package/dist/shell/appearance-controls.d.ts +13 -0
- package/dist/shell/appearance-controls.js +1 -0
- package/dist/shell/command-palette.d.ts +9 -0
- package/dist/shell/command-palette.js +1 -0
- package/dist/shell/config.d.ts +66 -0
- package/dist/shell/config.js +1 -0
- package/dist/shell/icon-rail.d.ts +2 -0
- package/dist/shell/icon-rail.js +1 -0
- package/dist/shell/index.d.ts +7 -0
- package/dist/shell/index.js +1 -0
- package/dist/shell/mobile-nav.d.ts +7 -0
- package/dist/shell/mobile-nav.js +1 -0
- package/dist/shell/module-sidebar.d.ts +9 -0
- package/dist/shell/module-sidebar.js +1 -0
- package/dist/shell/notifications.d.ts +5 -0
- package/dist/shell/notifications.js +1 -0
- package/dist/shell/placeholder-screen.d.ts +11 -0
- package/dist/shell/placeholder-screen.js +1 -0
- package/dist/shell/record-drawer.d.ts +32 -0
- package/dist/shell/record-drawer.js +1 -0
- package/dist/shell/registry.d.ts +24 -0
- package/dist/shell/registry.js +1 -0
- package/dist/shell/topbar.d.ts +9 -0
- package/dist/shell/topbar.js +1 -0
- package/dist/shell/use-active.d.ts +21 -0
- package/dist/shell/use-active.js +1 -0
- package/dist/shell/user-menu.d.ts +5 -0
- package/dist/shell/user-menu.js +1 -0
- package/dist/store/app-store.d.ts +10 -0
- package/dist/store/app-store.js +1 -0
- package/dist/store/drawer-store.d.ts +22 -0
- package/dist/store/drawer-store.js +1 -0
- package/dist/store/index.d.ts +5 -0
- package/dist/store/index.js +1 -0
- package/dist/store/settings-store.d.ts +22 -0
- package/dist/store/settings-store.js +1 -0
- package/dist/store/ui-store.d.ts +28 -0
- package/dist/store/ui-store.js +1 -0
- package/dist/styles.css +658 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.js +0 -0
- package/package.json +98 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Every release of `@waveinno/ui`. Add a line under **Unreleased** with each change; `./npmup.sh` moves it under the
|
|
4
|
+
new version when you release. Versions follow [semver](https://semver.org): patch = fix, minor = new component or
|
|
5
|
+
prop, major = a renamed or removed export or prop.
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
## 0.1.1 — 2026-10-02
|
|
10
|
+
|
|
11
|
+
- DonutChart: no floating tooltip on hover; it covered the centre readout, which already shows the hovered slice.
|
|
12
|
+
|
|
13
|
+
## 0.1.0 — 2026-10-02
|
|
14
|
+
|
|
15
|
+
First release on npm, as compiled JavaScript (one module per file, `"use client"` kept per module) with type
|
|
16
|
+
definitions; no source or source maps are published.
|
|
17
|
+
|
|
18
|
+
- **Tokens** in `@waveinno/ui/styles.css`: light and dark, three densities, motion that stops for reduced motion.
|
|
19
|
+
- **Brand**: official `WaveinnoLogo` and `WaveinnoSymbol` (from brand/waveinno-logo.svg), `WaveMark` app icon in seven
|
|
20
|
+
tones drawn from the logo colours, squircle or round, flat or 3D, with shine / float / pulse / flip motion;
|
|
21
|
+
`PoweredBy` signature (inline or floating, like WAVEMAP's), `Watermark`; logo file at `@waveinno/ui/brand/`.
|
|
22
|
+
- **Primitives**: Button (primary, secondary, ghost, subtle, danger, link; gradient, glow, dark, outline, elevated,
|
|
23
|
+
glass, white; pill shape, xl size), Badge (soft, solid, outline, dot, gradient, live), Input and Textarea with
|
|
24
|
+
error / warning / success states and leading / trailing slots, FormField, Select, searchable Combobox, Checkbox,
|
|
25
|
+
Switch, Segmented (pill, solid, outline, glass, sliding thumb, three sizes), Tabs (underline, pill, solid, enclosed,
|
|
26
|
+
sliding indicator), Calendar, DatePicker, DateTimePicker, DateRangePicker with presets, TimePicker (12/24 h),
|
|
27
|
+
Dialog (floating drawer that widens or goes full width; icon and eyebrow header; frosted footer), Sheet,
|
|
28
|
+
ConfirmDialog (item preview, type-to-confirm), DropdownMenu (rich items, account header, glass and dark), Popover
|
|
29
|
+
(arrow, glass, dark, brand), Tooltip, Progress (bar, gradient, striped, segmented, indeterminate) and ProgressRing,
|
|
30
|
+
Avatar (name colours, status, verified, gradient ring, square), Skeleton.
|
|
31
|
+
- **Patterns**: DataTable with advanced filters (text, select, number, date; all / any; chips; saved in views),
|
|
32
|
+
search, sort, columns, pinning, CSV export, five looks (default, striped, bordered, cards, minimal), inline cell
|
|
33
|
+
editing with validation, bulk edit and bulk delete, sticky action column; UserCell and RowActions; PageHero;
|
|
34
|
+
PageHeader; StatCard (icon, spark, target, gradient, comparison) and KpiCard; Money; ActivityFeed (list, cards,
|
|
35
|
+
compact); ActivityTimeline; ChangeHistory (field diffs); ChangeNotes (threaded, replies); Note (tones, outline,
|
|
36
|
+
gradient); Kanban; empty, error and loading states.
|
|
37
|
+
- **Charts**: TrendChart, BarChart, LineChart (comparison and target), DonutChart, GaugeChart, Heatmap, BarList,
|
|
38
|
+
ChartCard and a validated palette.
|
|
39
|
+
- **Shell**: AppShell (rail → panel → content → drawer, ⌘K), theme and density controls, record drawer.
|
package/LICENSE
ADDED
package/README.md
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @waveinno/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The WAVEINNO design system for React and Next.js: tokens, an application shell, primitives, patterns, charts and
|
|
4
|
+
the brand, in light and dark, in English and Bangla. Shipped as compiled JavaScript with type definitions.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install @waveinno/ui
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Set up (Next.js + Tailwind CSS v4)
|
|
11
|
+
|
|
12
|
+
```css
|
|
13
|
+
/* app/globals.css */
|
|
14
|
+
@import "tailwindcss";
|
|
15
|
+
@import "@waveinno/ui/styles.css";
|
|
16
|
+
/* Tailwind must see the class names the package uses. */
|
|
17
|
+
@source "../../node_modules/@waveinno/ui/dist";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
// app/layout.tsx — apply the saved theme before first paint (no flash)
|
|
22
|
+
import { themeBootScript } from "@waveinno/ui";
|
|
23
|
+
|
|
24
|
+
<head>
|
|
25
|
+
<script dangerouslySetInnerHTML={{ __html: themeBootScript("default") }} />
|
|
26
|
+
</head>;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Peer dependencies: `react` and `react-dom` 19+, `next` 16+, `tailwindcss` 4+. For Bangla and the Taka sign, load
|
|
30
|
+
Noto Sans Bengali and add it to `--font-inter` / `--font-jakarta` (Inter has no ৳).
|
|
31
|
+
|
|
32
|
+
## Use
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { Button, DataTable, DatePicker, PageHero, StatCard, WaveinnoLogo } from "@waveinno/ui";
|
|
36
|
+
|
|
37
|
+
<Button variant="primary">Save</Button>
|
|
38
|
+
<DatePicker value={day} onChange={setDay} locale="bn-BD" weekStartsOn={6} />
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Every component's file opens with a comment that says what it is for and the rule it keeps. Words on screen come
|
|
42
|
+
through `labels` props, so each product passes its own language.
|
|
43
|
+
|
|
44
|
+
## What is in it
|
|
45
|
+
|
|
46
|
+
| Group | Components |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| Primitives | Button (working + showcase variants), Badge (soft, solid, outline, dot, gradient, live), Input / Textarea (states, adornments), FormField, Select, Combobox (searchable), Checkbox, Switch, Segmented, Tabs (underline, pill, solid, enclosed), Calendar, DatePicker, DateTimePicker, DateRangePicker, TimePicker, Dialog (drawer that widens or goes full width), Sheet, ConfirmDialog, DropdownMenu (rich items, header, dark), Popover (arrow, dark, brand), Tooltip, Progress / ProgressRing, Avatar, Skeleton |
|
|
49
|
+
| Patterns | DataTable (advanced filters, saved views, five looks, inline and bulk edit, bulk delete, sticky actions), UserCell, RowActions, PageHero, PageHeader, StatCard, KpiCard, Money, ActivityFeed, ActivityTimeline, ChangeHistory, ChangeNotes, Note, Kanban, empty / error / loading states |
|
|
50
|
+
| Charts | TrendChart, BarChart, LineChart, DonutChart, GaugeChart, Heatmap, BarList, ChartCard, validated palette |
|
|
51
|
+
| Brand | WaveinnoLogo, WaveinnoSymbol, WaveMark (app icon: seven tones, round, 3D, animated), PoweredBy, Watermark; `@waveinno/ui/brand/waveinno-logo.svg` |
|
|
52
|
+
| Shell | AppShell (rail → panel → content → drawer, ⌘K), theme and density controls, record drawer |
|
|
53
|
+
|
|
54
|
+
## See every component
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install
|
|
58
|
+
npm run dev # playground on http://localhost:4500, live from src/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Adding or changing a component: see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
62
|
+
|
|
63
|
+
## Licence
|
|
64
|
+
|
|
65
|
+
Proprietary — © WAVEINNO. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1951.16 251.6"><defs><style>.cls-1{fill:#1a113e;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);}.cls-4{fill:url(#linear-gradient-3);}</style><linearGradient id="linear-gradient" x1="1728.11" y1="950.03" x2="1790.71" y2="950.03" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1437d3"/><stop offset="1" stop-color="#7560fd"/></linearGradient><linearGradient id="linear-gradient-2" x1="80.65" y1="939.38" x2="80.65" y2="1028.57" xlink:href="#linear-gradient"/><linearGradient id="linear-gradient-3" x1="247.96" y1="938.26" x2="247.96" y2="1109.67" xlink:href="#linear-gradient"/></defs><path class="cls-1" d="M1813.61,996.15a83,83,0,0,1,18.61-27.62A89.37,89.37,0,0,1,1861,950.21c11.11-4.5,23.12-6.6,36.33-6.6s25.22,2.1,36.33,6.6a83.21,83.21,0,0,1,47.14,45.94,90.43,90.43,0,0,1,6.6,35.13c0,12.91-2.1,24.62-6.6,35.42a86,86,0,0,1-18.62,27.93,87.76,87.76,0,0,1-28.52,18.31c-11.11,4.5-23.12,6.6-36.33,6.6s-25.22-2.1-36.33-6.6a89.35,89.35,0,0,1-28.82-18.31,81.45,81.45,0,0,1-18.61-27.93,93.49,93.49,0,0,1,0-70.55Zm40.53,54.94a46.08,46.08,0,0,0,43.23,30,43.2,43.2,0,0,0,18.62-3.91A41.77,41.77,0,0,0,1930.7,1067a52.44,52.44,0,0,0,9.61-15.91,61.14,61.14,0,0,0,0-39.63,54.86,54.86,0,0,0-9.61-15.61A47.06,47.06,0,0,0,1916,985.34a47.9,47.9,0,0,0-18.62-3.6,46.79,46.79,0,0,0-18.61,3.6,48.25,48.25,0,0,0-15,10.51,43.84,43.84,0,0,0-9.61,15.61,56.33,56.33,0,0,0,0,39.63Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M722.47,1061.5a74.57,74.57,0,0,1-16.65,25.57,73.37,73.37,0,0,1-25.27,16.65,86.77,86.77,0,0,1-32.11,6q-21,0-37.46-8.92a71.35,71.35,0,0,1-26.46-24.09,73.73,73.73,0,0,1-26.46,24.09q-16.5,8.91-37.46,8.92a85.28,85.28,0,0,1-31.82-6,73.83,73.83,0,0,1-42.21-42.22,86.77,86.77,0,0,1-5.95-32.11v-91h43.11v89.79c0,13.08,3.87,23.49,11.3,31.52s17.24,11.89,28.84,11.89a42.25,42.25,0,0,0,16.35-3.27,37.82,37.82,0,0,0,12.49-9.22,42.23,42.23,0,0,0,8.32-13.67,45.72,45.72,0,0,0,3-17.25V938.41h41v89.79a46.8,46.8,0,0,0,3,17.25,42.05,42.05,0,0,0,8.32,13.67,36.1,36.1,0,0,0,12.79,9.22,41.85,41.85,0,0,0,16,3.27c11.89,0,21.71-3.87,29.14-11.89s11-18.44,11-31.52V938.41h43.11v91A86.77,86.77,0,0,1,722.47,1061.5Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M759,988.36a84.63,84.63,0,0,1,18.43-28A83.17,83.17,0,0,1,805.71,942c10.71-4.46,22.6-6.54,35.38-6.54a98.64,98.64,0,0,1,34.49,5.95,82.52,82.52,0,0,1,27.06,17.24,79.35,79.35,0,0,1,17.54,26.16,85.9,85.9,0,0,1,6.24,33v88.89H885.1v-25.27c-4.46,8.62-11.9,15.46-21.71,20.52a75.91,75.91,0,0,1-64.22,1.18,70,70,0,0,1-24.67-17.83,81.81,81.81,0,0,1-16.06-27.06,98.91,98.91,0,0,1-6-34.49C752.49,1011,754.58,999.07,759,988.36Zm40.13,53.82a42,42,0,0,0,9.22,15.46,38,38,0,0,0,13.68,10.1,38.78,38.78,0,0,0,17.54,3.87,43.46,43.46,0,0,0,17.84-3.57,39.31,39.31,0,0,0,14-10.11,46.86,46.86,0,0,0,8.92-15.46,59.7,59.7,0,0,0,3-19.92,62.27,62.27,0,0,0-3.27-19.92,46.79,46.79,0,0,0-8.92-15.46,43.91,43.91,0,0,0-14-10.4,41.19,41.19,0,0,0-48.76,10.4,47.47,47.47,0,0,0-9.22,15.46,62.27,62.27,0,0,0-3.27,19.92A59.11,59.11,0,0,0,799.17,1042.18Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M1005.81,1106.69l-69-168.57h44.89l51.44,135.57,66.12-179.37h45.49l-84,212.37Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M1292.41,1074.29a75.91,75.91,0,0,1-19,18.73,81.4,81.4,0,0,1-25,12.19,94.91,94.91,0,0,1-29.14,4.46c-12.48,0-24.08-2.08-34.49-6.55a84.32,84.32,0,0,1-27.65-18.13,79.12,79.12,0,0,1-17.83-27.65c-4.46-10.71-6.55-22.3-6.55-35.08a89.47,89.47,0,0,1,6.55-34.79,86.11,86.11,0,0,1,18.13-27.35c7.43-7.73,16.65-13.68,27.35-18.14,10.41-4.46,22-6.54,34.49-6.54a96.51,96.51,0,0,1,36.57,6.84,80.21,80.21,0,0,1,27.65,19.92A95.31,95.31,0,0,1,1301,992.52a114.42,114.42,0,0,1,6.25,38.66H1176.46c1.49,13.08,6.54,23.48,14.57,31.51s17.84,11.89,29.73,11.89a51,51,0,0,0,25.87-6.84,38.71,38.71,0,0,0,16-17.83H1304A73.86,73.86,0,0,1,1292.41,1074.29Zm-42.81-94.55c-8-6.84-17.54-10.11-28.84-10.11S1200,973.2,1192.22,980s-12.79,16.05-14.87,27.65h87.41C1262.68,995.79,1257.63,986.58,1249.6,979.74Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M1337.9,874.49a23,23,0,0,1,32.11,0,21.1,21.1,0,0,1,6.54,15.76,21.75,21.75,0,0,1-6.54,16,22.26,22.26,0,0,1-32.11,0,21.76,21.76,0,0,1-6.55-16A21.11,21.11,0,0,1,1337.9,874.49Zm37.16,232.2h-42.22V938.41h42.22Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M1533.82,1016.9c0-13.08-3.86-23.48-11.59-31.51-8-8-18.14-11.89-30.33-11.89-12.49,0-22.6,3.86-30.33,11.89-8,8-11.89,18.43-11.89,31.51v89.79h-43.11v-91.27a78,78,0,0,1,6.54-32.41,75.62,75.62,0,0,1,17.54-25.27,82.26,82.26,0,0,1,27.06-16.35,96.94,96.94,0,0,1,34.19-5.95,98.17,98.17,0,0,1,34.19,5.95,76.94,76.94,0,0,1,44.6,41.62,82.88,82.88,0,0,1,6.24,32.41v91.27h-43.11Z" transform="translate(-36.28 -867.95)"/><path class="cls-1" d="M1777.9,1015.42v91.27h-43.11V1016.9c0-13.08-3.86-23.48-11.59-31.52-8-8-18.13-11.89-30.33-11.89-12.49,0-22.6,3.87-30.32,11.89-8,8-11.89,18.44-11.89,31.52v89.79h-43.11v-91.27a78,78,0,0,1,6.53-32.41,75.8,75.8,0,0,1,17.55-25.27,82.36,82.36,0,0,1,27-16.36,97.21,97.21,0,0,1,34.19-5.94,102.42,102.42,0,0,1,11.44.62,96.48,96.48,0,0,1,22.76,5.32,76,76,0,0,1,50.79,71.3C1777.89,1013.59,1777.9,1014.5,1777.9,1015.42Z" transform="translate(-36.28 -867.95)"/><path class="cls-2" d="M1728.11,921.1h.22c19-.47,37.93-.7,56.9-1.21a26.67,26.67,0,0,1,3.49.36c.2,2.21.46,4.13.52,6,.47,17.92,1,35.81,1.47,53.72v.19c-.52-1.3-1.08-2.57-1.66-3.83-.16-.39-.35-.77-.52-1.15-.36-.76-.72-1.52-1.1-2.27-.18-.38-.38-.74-.58-1.11s-.29-.6-.45-.89a101,101,0,0,0-6.29-10.39l-.74-1.07a103.42,103.42,0,0,0-6.95-8.78l-.82-.92c-.3-.34-.62-.69-.94-1s-.62-.67-1-1-.62-.67-.94-1l-1-1-2-1.92-1-.94-1-.92-1-.92-1-.89-1.28-1.07c-.63-.52-1.28-1-1.93-1.55-.37-.28-.73-.57-1.1-.84s-.79-.61-1.2-.91-.68-.5-1-.73l-1.32-.94-.95-.65c-1.14-.78-2.29-1.54-3.47-2.26-.39-.25-.78-.5-1.18-.73a102,102,0,0,0-10.12-5.39c-1-.46-2-.9-3-1.31-.49-.21-1-.42-1.46-.61s-.77-.33-1.16-.47l-1.18-.46C1730.28,921.87,1729.2,921.48,1728.11,921.1Z" transform="translate(-36.28 -867.95)"/><path class="cls-3" d="M125,1019.41l-8.72,9.16c-4.84-5.51-11.54-10.91-18.68-11.59-4.45-.44-9.17,0-13.64,0H49.73a13.45,13.45,0,0,1-13.45-13.45v-50.7a13.45,13.45,0,0,1,13.45-13.45H99.28a13.46,13.46,0,0,1,13.46,13.45v24.5c0,10.29-2.71,22.17,3,31.5A42.32,42.32,0,0,0,125,1019.41Z" transform="translate(-36.28 -867.95)"/><path class="cls-4" d="M401.1,938.26v81.47l-33.28.5a22.1,22.1,0,0,0-16.2,7.43l-66.45,74.6a22.09,22.09,0,0,1-16.51,7.41H247.59a11.38,11.38,0,0,1-11.37-11.38v-78.56h-8.54a24.74,24.74,0,0,0-18.37,8.18l-2.48,2.77-5.62,6.26-57.38,63.85a26.17,26.17,0,0,1-4.58,4,26.77,26.77,0,0,1-11,4.47,27.48,27.48,0,0,1-4.36.36H110.87a16.06,16.06,0,0,1-16.06-16.08v-42.43l21.49-22.59,8.72-9.16,64.68-68A37,37,0,0,1,216.47,940H248v85l.09-.09.07,21,89.94-96.13a37,37,0,0,1,26.77-11.48Z" transform="translate(-36.28 -867.95)"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./logo.js";export*from"./waveinno-logo.js";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* WAVEINNO BRAND
|
|
4
|
+
*
|
|
5
|
+
* One source for the mark, so the company never disappears behind whichever
|
|
6
|
+
* app is open. The earlier build made this mistake: the rail's mark became the
|
|
7
|
+
* active app's icon, and with WaveCommerce open there was no WAVEINNO anywhere
|
|
8
|
+
* on screen. A suite has to say both things at once — who makes this, and
|
|
9
|
+
* which product you are in — which is how Zoho, Atlassian and Workspace all
|
|
10
|
+
* handle it.
|
|
11
|
+
*
|
|
12
|
+
* The glyph is three strokes of a wave at falling opacity: the name is
|
|
13
|
+
* WAVE-inno, and a mark that argues with its own name is a mark nobody
|
|
14
|
+
* remembers.
|
|
15
|
+
*/
|
|
16
|
+
export declare function WaveGlyph({ className }: {
|
|
17
|
+
className?: string;
|
|
18
|
+
}): React.JSX.Element;
|
|
19
|
+
declare const sizes: {
|
|
20
|
+
readonly sm: "size-7";
|
|
21
|
+
readonly md: "size-[34px]";
|
|
22
|
+
readonly lg: "size-10";
|
|
23
|
+
readonly xl: "size-14";
|
|
24
|
+
readonly "2xl": "size-20";
|
|
25
|
+
};
|
|
26
|
+
declare const tones: {
|
|
27
|
+
readonly brand: {
|
|
28
|
+
readonly bg: "bg-[linear-gradient(145deg,#1f45ea_0%,#1437d3_38%,#7560fd_100%)]";
|
|
29
|
+
readonly glow: "0_6px_16px_-6px_rgba(20,55,211,.5)";
|
|
30
|
+
readonly mono: true;
|
|
31
|
+
readonly side: "#9aa6f5";
|
|
32
|
+
};
|
|
33
|
+
readonly royal: {
|
|
34
|
+
readonly bg: "bg-[linear-gradient(180deg,#3159f5_0%,#1437d3_55%,#0f2aa6_100%)]";
|
|
35
|
+
readonly glow: "0_6px_16px_-6px_rgba(20,55,211,.55)";
|
|
36
|
+
readonly mono: true;
|
|
37
|
+
readonly side: "#8ea0f2";
|
|
38
|
+
};
|
|
39
|
+
readonly violet: {
|
|
40
|
+
readonly bg: "bg-[linear-gradient(180deg,#8f7dff_0%,#7560fd_50%,#5a40e8_100%)]";
|
|
41
|
+
readonly glow: "0_6px_16px_-6px_rgba(117,96,253,.55)";
|
|
42
|
+
readonly mono: true;
|
|
43
|
+
readonly side: "#b9adff";
|
|
44
|
+
};
|
|
45
|
+
readonly aurora: {
|
|
46
|
+
readonly bg: "bg-[#120c33] bg-[radial-gradient(90%_90%_at_0%_100%,rgba(20,55,211,.95),transparent_60%),radial-gradient(80%_80%_at_100%_0%,rgba(117,96,253,.9),transparent_60%)]";
|
|
47
|
+
readonly glow: "0_6px_18px_-6px_rgba(60,50,200,.55)";
|
|
48
|
+
readonly mono: true;
|
|
49
|
+
readonly side: "#8c84d8";
|
|
50
|
+
};
|
|
51
|
+
readonly midnight: {
|
|
52
|
+
readonly bg: "bg-[linear-gradient(160deg,#2a1f66_0%,#1a113e_50%,#0a0720_100%)] ring-1 ring-inset ring-white/10";
|
|
53
|
+
readonly glow: "0_6px_16px_-6px_rgba(10,7,32,.6)";
|
|
54
|
+
readonly mono: true;
|
|
55
|
+
readonly side: "#7f78b0";
|
|
56
|
+
};
|
|
57
|
+
readonly light: {
|
|
58
|
+
readonly bg: "bg-[linear-gradient(180deg,#ffffff_0%,#f1f3fa_100%)] ring-1 ring-inset ring-[rgba(26,17,62,.08)]";
|
|
59
|
+
readonly glow: "0_6px_16px_-8px_rgba(26,17,62,.3)";
|
|
60
|
+
readonly mono: false;
|
|
61
|
+
readonly side: "#0f2aa6";
|
|
62
|
+
};
|
|
63
|
+
readonly glass: {
|
|
64
|
+
readonly bg: "bg-white/15 ring-1 ring-inset ring-white/35 backdrop-blur-md";
|
|
65
|
+
readonly glow: "0_6px_16px_-8px_rgba(5,8,22,.25)";
|
|
66
|
+
readonly mono: true;
|
|
67
|
+
readonly side: "rgba(255,255,255,.55)";
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** Tone names, for pickers and docs. */
|
|
71
|
+
export declare const WAVE_MARK_TONES: (keyof typeof tones)[];
|
|
72
|
+
export declare function WaveMark({ size, tone, shape, effect, animate, className, }: {
|
|
73
|
+
size?: keyof typeof sizes;
|
|
74
|
+
tone?: keyof typeof tones;
|
|
75
|
+
shape?: "squircle" | "round";
|
|
76
|
+
effect?: "flat" | "3d";
|
|
77
|
+
animate?: "shine" | "float" | "pulse" | "flip";
|
|
78
|
+
className?: string;
|
|
79
|
+
}): React.JSX.Element;
|
|
80
|
+
/** Mark plus name. Used wherever the company should be read, not just seen. */
|
|
81
|
+
export declare function WaveWordmark({ size, className, suffix, tone, }: {
|
|
82
|
+
size?: keyof typeof sizes;
|
|
83
|
+
className?: string;
|
|
84
|
+
/** "inverse" for dark or photographic backgrounds. */
|
|
85
|
+
tone?: "default" | "inverse";
|
|
86
|
+
/** The product this sits in front of, e.g. "WaveCRM". */
|
|
87
|
+
suffix?: string;
|
|
88
|
+
}): React.JSX.Element;
|
|
89
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Fragment as w,jsx as e,jsxs as n}from"react/jsx-runtime";import{cn as a}from"../../lib/utils.js";import{WaveinnoSymbol as _}from"./waveinno-logo.js";function v({className:r}){return n("svg",{viewBox:"0 0 24 24",className:a("size-4",r),fill:"none","aria-hidden":!0,children:[e("path",{d:"M2.5 9.5c2.4 0 2.4-3.6 4.8-3.6s2.4 3.6 4.8 3.6 2.4-3.6 4.8-3.6 2.4 3.6 4.6 3.6",stroke:"currentColor",strokeWidth:"2.1",strokeLinecap:"round"}),e("path",{d:"M2.5 14.5c2.4 0 2.4-3.6 4.8-3.6s2.4 3.6 4.8 3.6 2.4-3.6 4.8-3.6 2.4 3.6 4.6 3.6",stroke:"currentColor",strokeWidth:"2.1",strokeLinecap:"round",opacity:".62"}),e("path",{d:"M2.5 19.5c2.4 0 2.4-3.6 4.8-3.6s2.4 3.6 4.8 3.6 2.4-3.6 4.8-3.6 2.4 3.6 4.6 3.6",stroke:"currentColor",strokeWidth:"2.1",strokeLinecap:"round",opacity:".3"})]})}const u={sm:"size-7",md:"size-[34px]",lg:"size-10",xl:"size-14","2xl":"size-20"},b={brand:{bg:"bg-[linear-gradient(145deg,#1f45ea_0%,#1437d3_38%,#7560fd_100%)]",glow:"0_6px_16px_-6px_rgba(20,55,211,.5)",mono:!0,side:"#9aa6f5"},royal:{bg:"bg-[linear-gradient(180deg,#3159f5_0%,#1437d3_55%,#0f2aa6_100%)]",glow:"0_6px_16px_-6px_rgba(20,55,211,.55)",mono:!0,side:"#8ea0f2"},violet:{bg:"bg-[linear-gradient(180deg,#8f7dff_0%,#7560fd_50%,#5a40e8_100%)]",glow:"0_6px_16px_-6px_rgba(117,96,253,.55)",mono:!0,side:"#b9adff"},aurora:{bg:"bg-[#120c33] bg-[radial-gradient(90%_90%_at_0%_100%,rgba(20,55,211,.95),transparent_60%),radial-gradient(80%_80%_at_100%_0%,rgba(117,96,253,.9),transparent_60%)]",glow:"0_6px_18px_-6px_rgba(60,50,200,.55)",mono:!0,side:"#8c84d8"},midnight:{bg:"bg-[linear-gradient(160deg,#2a1f66_0%,#1a113e_50%,#0a0720_100%)] ring-1 ring-inset ring-white/10",glow:"0_6px_16px_-6px_rgba(10,7,32,.6)",mono:!0,side:"#7f78b0"},light:{bg:"bg-[linear-gradient(180deg,#ffffff_0%,#f1f3fa_100%)] ring-1 ring-inset ring-[rgba(26,17,62,.08)]",glow:"0_6px_16px_-8px_rgba(26,17,62,.3)",mono:!1,side:"#0f2aa6"},glass:{bg:"bg-white/15 ring-1 ring-inset ring-white/35 backdrop-blur-md",glow:"0_6px_16px_-8px_rgba(5,8,22,.25)",mono:!0,side:"rgba(255,255,255,.55)"}},z=Object.keys(b),m={sm:1,md:2,lg:2,xl:3,"2xl":4};function h({size:r="md",tone:p="brand",shape:o="squircle",effect:i="flat",animate:t,className:f}){const s=b[p],l=i==="3d",d=m[r],c=l?[...Array.from({length:d},()=>`drop-shadow(0 1px 0 ${s.side})`),`drop-shadow(0 ${d+1}px ${d+1}px rgba(5,8,22,.45))`].join(" "):"drop-shadow(0 1px 1px rgba(5,8,22,.25))",g=o==="round"?"rounded-full":"rounded-[22.5%]",x=n("span",{className:a("relative isolate grid shrink-0 place-items-center overflow-hidden",g,"before:absolute before:inset-x-0 before:top-0 before:-z-10 before:h-1/2 before:bg-[linear-gradient(180deg,rgba(255,255,255,.22),transparent)]",l&&"after:absolute after:-left-[15%] after:-top-[25%] after:-z-10 after:h-[70%] after:w-[80%] after:rounded-full after:bg-[radial-gradient(closest-side,rgba(255,255,255,.35),transparent)]",s.bg,s.mono&&"text-white",u[r],t==="float"&&"wm-float",t==="flip"&&"wm-flip",!t||t==="shine"?f:void 0),style:{boxShadow:l?`inset 0 2px 0 rgba(255,255,255,.45), inset 0 -3px 0 rgba(5,8,22,.22), inset 0 -14px 22px -10px rgba(5,8,22,.35), 0 2px 3px rgba(5,8,22,.2), 0 14px 28px -12px ${s.glow.split("_").pop()}`:`inset 0 1px 0 rgba(255,255,255,.35), inset 0 -8px 16px -8px rgba(5,8,22,.28), 0 1px 2px rgba(5,8,22,.18), ${s.glow.replaceAll("_"," ")}`},"aria-hidden":!0,children:[e(_,{title:"",mono:s.mono,className:a("h-auto",l?"-translate-y-[2%]":"translate-y-[2%]",o==="round"?"w-[58%]":"w-[64%]"),style:{filter:c}}),t==="shine"?e("span",{"aria-hidden":!0,className:"wm-shine pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-[linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent)]"}):null]});return t!=="pulse"&&t!=="float"&&t!=="flip"?x:n("span",{className:a("relative inline-grid shrink-0 place-items-center",f),"aria-hidden":!0,children:[t==="pulse"?n(w,{children:[e("span",{className:a("wm-pulse absolute inset-0 bg-[#4f5ff0]/40",g)}),e("span",{className:a("wm-pulse-late absolute inset-0 bg-[#7560fd]/35",g)})]}):null,x]})}function W({size:r="md",className:p,suffix:o,tone:i="default"}){return n("span",{className:a("flex items-center gap-2.5",p),children:[e(h,{size:r}),n("span",{className:"flex min-w-0 flex-col leading-none",children:[e("span",{className:a("disp text-[13px] font-bold tracking-[0.14em]",i==="inverse"?"text-white":"text-text"),children:"WAVEINNO"}),o?e("span",{className:a("mt-1 truncate text-[11px] font-medium",i==="inverse"?"text-white/70":"text-muted"),children:o}):null]})]})}export{z as WAVE_MARK_TONES,v as WaveGlyph,h as WaveMark,W as WaveWordmark};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/** Symbol and wordmark. Wherever the company should be read, not just seen. */
|
|
3
|
+
export declare function WaveinnoLogo({ className, tone, title, }: {
|
|
4
|
+
className?: string;
|
|
5
|
+
/** "inverse" for dark or photographic backgrounds in light mode. */
|
|
6
|
+
tone?: "default" | "inverse";
|
|
7
|
+
/** Accessible name; pass "" when a visible name sits next to it. */
|
|
8
|
+
title?: string;
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
/** The symbol alone — favicons, tight spaces. Size it by height or width. `mono` draws it in currentColor (white on a brand tile). */
|
|
11
|
+
export declare function WaveinnoSymbol({ className, style, title, mono, }: {
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: React.CSSProperties;
|
|
14
|
+
title?: string;
|
|
15
|
+
mono?: boolean;
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
declare const corners: {
|
|
18
|
+
readonly "bottom-left": "bottom-2.5 left-2.5";
|
|
19
|
+
readonly "bottom-right": "bottom-2.5 right-2.5";
|
|
20
|
+
readonly "top-left": "top-2.5 left-2.5";
|
|
21
|
+
readonly "top-right": "top-2.5 right-2.5";
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The WAVEINNO signature, the way WAVEMAP signs its maps: the product's mark
|
|
25
|
+
* and name, then "powered by" and the WAVEINNO logo.
|
|
26
|
+
*
|
|
27
|
+
* `inline` sits in a footer, a sign-in page or a receipt. `floating` is a small
|
|
28
|
+
* frosted pill pinned to a corner of its (relative) parent — maps, kiosk and
|
|
29
|
+
* gate screens, shared dashboards — that never takes pointer events from what
|
|
30
|
+
* is underneath. Without `product` it is just "powered by WAVEINNO".
|
|
31
|
+
*/
|
|
32
|
+
export declare function PoweredBy({ product, icon, variant, position, label, className, }: {
|
|
33
|
+
/** Product name as sold, e.g. "ParkingOS". Shown in capitals. */
|
|
34
|
+
product?: string;
|
|
35
|
+
/** The product's own mark, shown before its name. */
|
|
36
|
+
icon?: React.ReactNode;
|
|
37
|
+
variant?: "inline" | "floating";
|
|
38
|
+
position?: keyof typeof corners;
|
|
39
|
+
/** Translated "powered by". */
|
|
40
|
+
label?: string;
|
|
41
|
+
className?: string;
|
|
42
|
+
}): React.JSX.Element;
|
|
43
|
+
/**
|
|
44
|
+
* A faint WAVEINNO symbol behind content — printed receipts, exported reports,
|
|
45
|
+
* screenshots that leave the building. Fills its (relative) parent and stays
|
|
46
|
+
* out of the way of selection and clicks.
|
|
47
|
+
*/
|
|
48
|
+
export declare function Watermark({ opacity, className }: {
|
|
49
|
+
opacity?: number;
|
|
50
|
+
className?: string;
|
|
51
|
+
}): React.JSX.Element;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as c from"react";import{cn as i}from"../../lib/utils.js";const h=["M1813.61,996.15a83,83,0,0,1,18.61-27.62A89.37,89.37,0,0,1,1861,950.21c11.11-4.5,23.12-6.6,36.33-6.6s25.22,2.1,36.33,6.6a83.21,83.21,0,0,1,47.14,45.94,90.43,90.43,0,0,1,6.6,35.13c0,12.91-2.1,24.62-6.6,35.42a86,86,0,0,1-18.62,27.93,87.76,87.76,0,0,1-28.52,18.31c-11.11,4.5-23.12,6.6-36.33,6.6s-25.22-2.1-36.33-6.6a89.35,89.35,0,0,1-28.82-18.31,81.45,81.45,0,0,1-18.61-27.93,93.49,93.49,0,0,1,0-70.55Zm40.53,54.94a46.08,46.08,0,0,0,43.23,30,43.2,43.2,0,0,0,18.62-3.91A41.77,41.77,0,0,0,1930.7,1067a52.44,52.44,0,0,0,9.61-15.91,61.14,61.14,0,0,0,0-39.63,54.86,54.86,0,0,0-9.61-15.61A47.06,47.06,0,0,0,1916,985.34a47.9,47.9,0,0,0-18.62-3.6,46.79,46.79,0,0,0-18.61,3.6,48.25,48.25,0,0,0-15,10.51,43.84,43.84,0,0,0-9.61,15.61,56.33,56.33,0,0,0,0,39.63Z","M722.47,1061.5a74.57,74.57,0,0,1-16.65,25.57,73.37,73.37,0,0,1-25.27,16.65,86.77,86.77,0,0,1-32.11,6q-21,0-37.46-8.92a71.35,71.35,0,0,1-26.46-24.09,73.73,73.73,0,0,1-26.46,24.09q-16.5,8.91-37.46,8.92a85.28,85.28,0,0,1-31.82-6,73.83,73.83,0,0,1-42.21-42.22,86.77,86.77,0,0,1-5.95-32.11v-91h43.11v89.79c0,13.08,3.87,23.49,11.3,31.52s17.24,11.89,28.84,11.89a42.25,42.25,0,0,0,16.35-3.27,37.82,37.82,0,0,0,12.49-9.22,42.23,42.23,0,0,0,8.32-13.67,45.72,45.72,0,0,0,3-17.25V938.41h41v89.79a46.8,46.8,0,0,0,3,17.25,42.05,42.05,0,0,0,8.32,13.67,36.1,36.1,0,0,0,12.79,9.22,41.85,41.85,0,0,0,16,3.27c11.89,0,21.71-3.87,29.14-11.89s11-18.44,11-31.52V938.41h43.11v91A86.77,86.77,0,0,1,722.47,1061.5Z","M759,988.36a84.63,84.63,0,0,1,18.43-28A83.17,83.17,0,0,1,805.71,942c10.71-4.46,22.6-6.54,35.38-6.54a98.64,98.64,0,0,1,34.49,5.95,82.52,82.52,0,0,1,27.06,17.24,79.35,79.35,0,0,1,17.54,26.16,85.9,85.9,0,0,1,6.24,33v88.89H885.1v-25.27c-4.46,8.62-11.9,15.46-21.71,20.52a75.91,75.91,0,0,1-64.22,1.18,70,70,0,0,1-24.67-17.83,81.81,81.81,0,0,1-16.06-27.06,98.91,98.91,0,0,1-6-34.49C752.49,1011,754.58,999.07,759,988.36Zm40.13,53.82a42,42,0,0,0,9.22,15.46,38,38,0,0,0,13.68,10.1,38.78,38.78,0,0,0,17.54,3.87,43.46,43.46,0,0,0,17.84-3.57,39.31,39.31,0,0,0,14-10.11,46.86,46.86,0,0,0,8.92-15.46,59.7,59.7,0,0,0,3-19.92,62.27,62.27,0,0,0-3.27-19.92,46.79,46.79,0,0,0-8.92-15.46,43.91,43.91,0,0,0-14-10.4,41.19,41.19,0,0,0-48.76,10.4,47.47,47.47,0,0,0-9.22,15.46,62.27,62.27,0,0,0-3.27,19.92A59.11,59.11,0,0,0,799.17,1042.18Z","M1005.81,1106.69l-69-168.57h44.89l51.44,135.57,66.12-179.37h45.49l-84,212.37Z","M1292.41,1074.29a75.91,75.91,0,0,1-19,18.73,81.4,81.4,0,0,1-25,12.19,94.91,94.91,0,0,1-29.14,4.46c-12.48,0-24.08-2.08-34.49-6.55a84.32,84.32,0,0,1-27.65-18.13,79.12,79.12,0,0,1-17.83-27.65c-4.46-10.71-6.55-22.3-6.55-35.08a89.47,89.47,0,0,1,6.55-34.79,86.11,86.11,0,0,1,18.13-27.35c7.43-7.73,16.65-13.68,27.35-18.14,10.41-4.46,22-6.54,34.49-6.54a96.51,96.51,0,0,1,36.57,6.84,80.21,80.21,0,0,1,27.65,19.92A95.31,95.31,0,0,1,1301,992.52a114.42,114.42,0,0,1,6.25,38.66H1176.46c1.49,13.08,6.54,23.48,14.57,31.51s17.84,11.89,29.73,11.89a51,51,0,0,0,25.87-6.84,38.71,38.71,0,0,0,16-17.83H1304A73.86,73.86,0,0,1,1292.41,1074.29Zm-42.81-94.55c-8-6.84-17.54-10.11-28.84-10.11S1200,973.2,1192.22,980s-12.79,16.05-14.87,27.65h87.41C1262.68,995.79,1257.63,986.58,1249.6,979.74Z","M1337.9,874.49a23,23,0,0,1,32.11,0,21.1,21.1,0,0,1,6.54,15.76,21.75,21.75,0,0,1-6.54,16,22.26,22.26,0,0,1-32.11,0,21.76,21.76,0,0,1-6.55-16A21.11,21.11,0,0,1,1337.9,874.49Zm37.16,232.2h-42.22V938.41h42.22Z","M1533.82,1016.9c0-13.08-3.86-23.48-11.59-31.51-8-8-18.14-11.89-30.33-11.89-12.49,0-22.6,3.86-30.33,11.89-8,8-11.89,18.43-11.89,31.51v89.79h-43.11v-91.27a78,78,0,0,1,6.54-32.41,75.62,75.62,0,0,1,17.54-25.27,82.26,82.26,0,0,1,27.06-16.35,96.94,96.94,0,0,1,34.19-5.95,98.17,98.17,0,0,1,34.19,5.95,76.94,76.94,0,0,1,44.6,41.62,82.88,82.88,0,0,1,6.24,32.41v91.27h-43.11Z","M1777.9,1015.42v91.27h-43.11V1016.9c0-13.08-3.86-23.48-11.59-31.52-8-8-18.13-11.89-30.33-11.89-12.49,0-22.6,3.87-30.32,11.89-8,8-11.89,18.44-11.89,31.52v89.79h-43.11v-91.27a78,78,0,0,1,6.53-32.41,75.8,75.8,0,0,1,17.55-25.27,82.36,82.36,0,0,1,27-16.36,97.21,97.21,0,0,1,34.19-5.94,102.42,102.42,0,0,1,11.44.62,96.48,96.48,0,0,1,22.76,5.32,76,76,0,0,1,50.79,71.3C1777.89,1013.59,1777.9,1014.5,1777.9,1015.42Z"],u="M1728.11,921.1h.22c19-.47,37.93-.7,56.9-1.21a26.67,26.67,0,0,1,3.49.36c.2,2.21.46,4.13.52,6,.47,17.92,1,35.81,1.47,53.72v.19c-.52-1.3-1.08-2.57-1.66-3.83-.16-.39-.35-.77-.52-1.15-.36-.76-.72-1.52-1.1-2.27-.18-.38-.38-.74-.58-1.11s-.29-.6-.45-.89a101,101,0,0,0-6.29-10.39l-.74-1.07a103.42,103.42,0,0,0-6.95-8.78l-.82-.92c-.3-.34-.62-.69-.94-1s-.62-.67-1-1-.62-.67-.94-1l-1-1-2-1.92-1-.94-1-.92-1-.92-1-.89-1.28-1.07c-.63-.52-1.28-1-1.93-1.55-.37-.28-.73-.57-1.1-.84s-.79-.61-1.2-.91-.68-.5-1-.73l-1.32-.94-.95-.65c-1.14-.78-2.29-1.54-3.47-2.26-.39-.25-.78-.5-1.18-.73a102,102,0,0,0-10.12-5.39c-1-.46-2-.9-3-1.31-.49-.21-1-.42-1.46-.61s-.77-.33-1.16-.47l-1.18-.46C1730.28,921.87,1729.2,921.48,1728.11,921.1Z",d="M125,1019.41l-8.72,9.16c-4.84-5.51-11.54-10.91-18.68-11.59-4.45-.44-9.17,0-13.64,0H49.73a13.45,13.45,0,0,1-13.45-13.45v-50.7a13.45,13.45,0,0,1,13.45-13.45H99.28a13.46,13.46,0,0,1,13.46,13.45v24.5c0,10.29-2.71,22.17,3,31.5A42.32,42.32,0,0,0,125,1019.41Z",p="M401.1,938.26v81.47l-33.28.5a22.1,22.1,0,0,0-16.2,7.43l-66.45,74.6a22.09,22.09,0,0,1-16.51,7.41H247.59a11.38,11.38,0,0,1-11.37-11.38v-78.56h-8.54a24.74,24.74,0,0,0-18.37,8.18l-2.48,2.77-5.62,6.26-57.38,63.85a26.17,26.17,0,0,1-4.58,4,26.77,26.77,0,0,1-11,4.47,27.48,27.48,0,0,1-4.36.36H110.87a16.06,16.06,0,0,1-16.06-16.08v-42.43l21.49-22.59,8.72-9.16,64.68-68A37,37,0,0,1,216.47,940H248v85l.09-.09.07,21,89.94-96.13a37,37,0,0,1,26.77-11.48Z";function f({id:t}){return n("defs",{children:[n("linearGradient",{id:`${t}-a`,x1:"80.65",y1:"939.38",x2:"80.65",y2:"1028.57",gradientUnits:"userSpaceOnUse",children:[e("stop",{offset:"0",stopColor:"#1437d3"}),e("stop",{offset:"1",stopColor:"#7560fd"})]}),n("linearGradient",{id:`${t}-b`,x1:"247.96",y1:"938.26",x2:"247.96",y2:"1109.67",gradientUnits:"userSpaceOnUse",children:[e("stop",{offset:"0",stopColor:"#1437d3"}),e("stop",{offset:"1",stopColor:"#7560fd"})]}),n("linearGradient",{id:`${t}-c`,x1:"1728.11",y1:"950.03",x2:"1790.71",y2:"950.03",gradientUnits:"userSpaceOnUse",children:[e("stop",{offset:"0",stopColor:"#1437d3"}),e("stop",{offset:"1",stopColor:"#7560fd"})]})]})}function v({className:t,tone:r="default",title:o="WAVEINNO"}){const a=c.useId().replace(/:/g,"");return n("svg",{viewBox:"-8 -8 1967.16 267.6",overflow:"visible",className:i("h-6 w-auto shrink-0",r==="inverse"?"text-white":"text-text",t),role:o?"img":void 0,"aria-label":o||void 0,"aria-hidden":o?void 0:!0,children:[e(f,{id:a}),n("g",{transform:"translate(-36.28 -867.95)",children:[h.map(s=>e("path",{d:s,fill:"currentColor"},s.slice(0,24))),e("path",{d:u,fill:`url(#${a}-c)`}),e("path",{d,fill:`url(#${a}-a)`}),e("path",{d:p,fill:`url(#${a}-b)`})]})]})}function g({className:t,style:r,title:o="WAVEINNO",mono:a=!1}){const s=c.useId().replace(/:/g,"");return n("svg",{viewBox:"36.28 938.26 364.82 171.41",className:i("h-6 w-auto shrink-0",t),style:r,role:o?"img":void 0,"aria-label":o||void 0,"aria-hidden":o?void 0:!0,children:[a?null:e(f,{id:s}),e("path",{d,fill:a?"currentColor":`url(#${s}-a)`}),e("path",{d:p,fill:a?"currentColor":`url(#${s}-b)`})]})}const x={"bottom-left":"bottom-2.5 left-2.5","bottom-right":"bottom-2.5 right-2.5","top-left":"top-2.5 left-2.5","top-right":"top-2.5 right-2.5"};function N({product:t,icon:r,variant:o="inline",position:a="bottom-left",label:s="powered by",className:m}){const l=n("span",{className:i("flex items-center gap-1 font-medium text-muted",t?"mt-0.5 text-[9px]":"text-[11px]"),children:[s,e(v,{title:"",className:t?"h-[9px]":"h-[11px]"})]});return n("div",{"aria-label":t?`${t}, ${s} WAVEINNO`:`${s} WAVEINNO`,role:"img",className:i("flex select-none items-center gap-1.5",o==="floating"&&i("pointer-events-none absolute z-10 rounded-[11px] border border-border bg-canvas/75 py-[5px] pl-1.5 pr-2.5 shadow-[0_4px_14px_-6px_rgba(10,15,46,.35)] backdrop-blur-md",x[a]),m),children:[r?e("span",{className:"grid shrink-0 place-items-center",children:r}):null,t?n("span",{className:"flex flex-col leading-none",children:[e("b",{className:"text-[12.5px] font-extrabold tracking-[0.14em] text-text",children:t.toUpperCase()}),l]}):l]})}function y({opacity:t=.05,className:r}){return e("div",{"aria-hidden":!0,className:i("pointer-events-none absolute inset-0 grid select-none place-items-center overflow-hidden",r),children:e("div",{style:{opacity:t},className:"w-[55%] max-w-[420px] -rotate-12",children:e(g,{title:"",className:"h-auto w-full"})})})}export{N as PoweredBy,y as Watermark,v as WaveinnoLogo,g as WaveinnoSymbol};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SeriesMeta } from "./chart-card";
|
|
3
|
+
export interface BarSeries extends SeriesMeta {
|
|
4
|
+
key: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Magnitude comparison.
|
|
8
|
+
*
|
|
9
|
+
* Bars are rounded 4px at the data end only and stay anchored to the baseline —
|
|
10
|
+
* a bar rounded at both ends no longer starts at zero, which is a lie about the
|
|
11
|
+
* data. Stacked segments keep a 2px surface gap so adjacent fills never merge.
|
|
12
|
+
*/
|
|
13
|
+
export declare function BarChart({ data, xKey, series, format, stacked, horizontal, }: {
|
|
14
|
+
data: Record<string, string | number>[];
|
|
15
|
+
xKey: string;
|
|
16
|
+
series: BarSeries[];
|
|
17
|
+
format?: (v: number) => string;
|
|
18
|
+
stacked?: boolean;
|
|
19
|
+
horizontal?: boolean;
|
|
20
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{Fragment as m,jsx as i,jsxs as o}from"react/jsx-runtime";import{Bar as S,BarChart as v,CartesianGrid as h,ResponsiveContainer as C,Tooltip as x,XAxis as f,YAxis as d}from"recharts";import{ChartTooltip as L}from"./chart-card.js";import{AXIS as t}from"./palette.js";function w({data:u,xKey:l,series:s,format:n=e=>String(e),stacked:y,horizontal:a}){return i(C,{width:"100%",height:"100%",children:o(v,{data:u,layout:a?"vertical":"horizontal",margin:{top:6,right:12,bottom:0,left:a?8:-18},barGap:2,barCategoryGap:"28%",children:[i(h,{vertical:!!a,horizontal:!a,stroke:t.grid}),a?o(m,{children:[i(f,{type:"number",tickLine:!1,axisLine:!1,tickFormatter:e=>n(e),tick:{fill:t.tick,fontSize:t.tickSize}}),i(d,{type:"category",dataKey:l,tickLine:!1,axisLine:!1,width:112,tick:{fill:t.tick,fontSize:t.tickSize}})]}):o(m,{children:[i(f,{dataKey:l,tickLine:!1,axisLine:!1,tickMargin:8,tick:{fill:t.tick,fontSize:t.tickSize}}),i(d,{tickLine:!1,axisLine:!1,width:64,tickFormatter:e=>n(e),tick:{fill:t.tick,fontSize:t.tickSize}})]}),i(x,{cursor:{fill:"var(--hover)"},content:e=>{const{active:b,payload:c,label:p}=e;return!b||!c?.length?null:i(L,{label:p,rows:c.map(r=>{const k=s.find(g=>g.key===r.dataKey);return{id:r.dataKey,label:k?.label??r.dataKey,value:n(r.value),color:k?.color??t.tick}})})}}),s.map(e=>i(S,{dataKey:e.key,name:e.label,fill:e.color,stackId:y?"1":void 0,radius:a?[0,4,4,0]:[4,4,0,0],isAnimationActive:!0,animationDuration:600},e.key))]})})}export{w as BarChart};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface BarListItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
value: number;
|
|
6
|
+
/** Extra text after the label: an area, a count, a change. */
|
|
7
|
+
hint?: React.ReactNode;
|
|
8
|
+
href?: string;
|
|
9
|
+
icon?: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ranked list — the label sits on its own bar, longest first: top car parks by
|
|
13
|
+
* revenue, busiest gates, plans by subscribers.
|
|
14
|
+
*
|
|
15
|
+
* Reads faster than a bar chart for "who leads" questions because the names
|
|
16
|
+
* are where the eye already is. Bars are scaled to the leader, so the first is
|
|
17
|
+
* always full and the gaps are the story.
|
|
18
|
+
*/
|
|
19
|
+
export declare function BarList({ items, format, sort, color, className, }: {
|
|
20
|
+
items: BarListItem[];
|
|
21
|
+
format?: (v: number) => string;
|
|
22
|
+
/** Largest first (default). Turn off when the order means something else, e.g. a time sequence. */
|
|
23
|
+
sort?: boolean;
|
|
24
|
+
/** Bar fill; a light tint keeps the label readable on top of it. */
|
|
25
|
+
color?: string;
|
|
26
|
+
className?: string;
|
|
27
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as t,jsxs as r}from"react/jsx-runtime";import{cn as l}from"../../lib/utils.js";function x({items:n,format:o=a=>a.toLocaleString(),sort:i=!0,color:c="var(--primary-subtle)",className:m}){const a=i?[...n].sort((e,s)=>s.value-e.value):n,u=Math.max(1,...a.map(e=>e.value));return t("ul",{className:l("space-y-1.5",m),children:a.map(e=>{const s=e.href?"a":"div";return t("li",{children:r(s,{...e.href?{href:e.href}:{},className:l("group flex items-center gap-3",e.href&&"cursor-pointer"),children:[r("div",{className:"relative h-8 min-w-0 flex-1 overflow-hidden rounded-[7px]",children:[t("div",{className:"absolute inset-y-0 left-0 rounded-[7px] transition-[width] duration-700 ease-[var(--ease)] group-hover:brightness-95",style:{width:`${Math.max(2,e.value/u*100)}%`,background:c}}),r("div",{className:"relative flex h-full items-center gap-2 px-2.5 text-[13px]",children:[e.icon?t("span",{className:"shrink-0 text-muted [&>svg]:size-4",children:e.icon}):null,t("span",{className:"truncate font-medium text-text",children:e.label}),e.hint?t("span",{className:"truncate text-[12px] text-muted",children:e.hint}):null]})]}),t("span",{className:"num w-20 shrink-0 text-right text-[13px] font-medium text-text",children:o(e.value)})]})},e.id)})})}export{x as BarList};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface SeriesMeta {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
color: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Chart chrome — title, legend, plot.
|
|
9
|
+
*
|
|
10
|
+
* The legend is not optional above one series: identity must never be carried
|
|
11
|
+
* by colour alone (§2.6). A single-series chart gets no legend box, because the
|
|
12
|
+
* title already names it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ChartCard({ title, description, series, action, children, className, height, }: {
|
|
15
|
+
title: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
series?: SeriesMeta[];
|
|
18
|
+
action?: React.ReactNode;
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
height?: number;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
/** Tooltip surface — same raised token as menus, so overlays feel like one family. */
|
|
24
|
+
export declare function ChartTooltip({ label, rows, }: {
|
|
25
|
+
label?: string;
|
|
26
|
+
rows: {
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
value: string;
|
|
30
|
+
color: string;
|
|
31
|
+
}[];
|
|
32
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Card as o}from"../ui/card.js";import{cn as c}from"../../lib/utils.js";function g({title:s,description:l,series:t,action:r,children:n,className:m,height:d=240}){return a(o,{className:c("flex flex-col",m),children:[a("div",{className:"mb-3 flex flex-wrap items-start justify-between gap-3",children:[a("div",{className:"min-w-0",children:[e("h3",{className:"text-[13px] font-semibold text-text",children:s}),l?e("p",{className:"mt-0.5 text-xs text-muted",children:l}):null]}),r]}),t&&t.length>1?e("ul",{className:"mb-3 flex flex-wrap items-center gap-x-4 gap-y-1.5",children:t.map(i=>a("li",{className:"flex items-center gap-1.5 text-xs text-muted",children:[e("span",{className:"size-2 shrink-0 rounded-[2px]",style:{background:i.color},"aria-hidden":!0}),i.label]},i.id))}):null,e("div",{style:{height:d},className:"min-w-0",children:n})]})}function N({label:s,rows:l}){return a("div",{className:"rounded-ctl border border-border bg-raised px-2.5 py-2 shadow-elev3",children:[s?e("p",{className:"mb-1.5 text-[11px] font-medium text-muted",children:s}):null,e("ul",{className:"space-y-1",children:l.map(t=>a("li",{className:"flex items-center gap-2 text-xs",children:[e("span",{className:"size-2 shrink-0 rounded-[2px]",style:{background:t.color},"aria-hidden":!0}),e("span",{className:"text-body",children:t.label}),e("span",{className:"num ml-auto pl-3 font-medium text-text",children:t.value})]},t.id))})]})}export{g as ChartCard,N as ChartTooltip};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Share of a whole — donut with the total in the hole and a legend that carries
|
|
4
|
+
* the numbers.
|
|
5
|
+
*
|
|
6
|
+
* Six slices at most: past that, a donut is a guessing game, so the smallest
|
|
7
|
+
* fold into "Other" (pass `maxSlices`). The legend always shows value and
|
|
8
|
+
* percentage, because angles are the hardest thing for eyes to compare.
|
|
9
|
+
* Hovering a slice (or its legend row) reads it out in the hole — no floating
|
|
10
|
+
* tooltip, which would sit on top of that same readout.
|
|
11
|
+
*/
|
|
12
|
+
export interface DonutDatum {
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
value: number;
|
|
16
|
+
color?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function DonutChart({ data, format, centerLabel, centerValue, maxSlices, otherLabel, height, legend, className, }: {
|
|
19
|
+
data: DonutDatum[];
|
|
20
|
+
format?: (v: number) => string;
|
|
21
|
+
centerLabel?: string;
|
|
22
|
+
/** Shown in the hole; defaults to the formatted total. */
|
|
23
|
+
centerValue?: React.ReactNode;
|
|
24
|
+
maxSlices?: number;
|
|
25
|
+
otherLabel?: string;
|
|
26
|
+
height?: number;
|
|
27
|
+
legend?: "right" | "bottom" | "none";
|
|
28
|
+
className?: string;
|
|
29
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as t,jsxs as c}from"react/jsx-runtime";import*as f from"react";import{Cell as D,Pie as M,PieChart as A,ResponsiveContainer as E}from"recharts";import{cn as N}from"../../lib/utils.js";import{SERIES as y}from"./palette.js";function _({data:d,format:m=a=>a.toLocaleString(),centerLabel:R="Total",centerValue:k,maxSlices:p=6,otherLabel:x="Other",height:w=220,legend:v="right",className:C}){const[a,r]=f.useState(null),l=f.useMemo(()=>{const e=[...d].sort((o,i)=>i.value-o.value),n=e.slice(0,p-(e.length>p?1:0)),h=e.slice(n.length),b=n.map((o,i)=>({...o,color:o.color??y[i%y.length]}));return h.length&&b.push({id:"__other",label:x,value:h.reduce((o,i)=>o+i.value,0),color:"var(--border2)"}),b},[d,p,x]),u=l.reduce((e,n)=>e+n.value,0),g=e=>u?`${(e/u*100).toFixed(e/u<.1?1:0)}%`:"0%",s=a!==null?l[a]:null;return c("div",{className:N("flex gap-5",v==="bottom"?"flex-col":"flex-col sm:flex-row sm:items-center",C),children:[c("div",{className:"relative mx-auto aspect-square w-full max-w-[220px] shrink-0",style:{height:w},children:[t(E,{width:"100%",height:"100%",children:t(A,{children:t(M,{data:l,dataKey:"value",nameKey:"label",innerRadius:"68%",outerRadius:"92%",paddingAngle:l.length>1?2:0,cornerRadius:4,stroke:"var(--raised)",strokeWidth:2,onMouseEnter:(e,n)=>r(n),onMouseLeave:()=>r(null),isAnimationActive:!0,animationDuration:700,children:l.map((e,n)=>t(D,{fill:e.color,fillOpacity:a===null||a===n?1:.35,style:{transition:"fill-opacity 150ms"}},e.id))})})}),t("div",{className:"pointer-events-none absolute inset-0 grid place-items-center text-center",children:c("div",{children:[t("p",{className:"text-[11px] font-medium uppercase tracking-[0.06em] text-muted",children:s?s.label:R}),t("p",{className:"num disp mt-0.5 text-[20px] font-semibold leading-none text-text",children:s?m(s.value):k??m(u)}),s?t("p",{className:"num mt-1 text-[11.5px] text-muted",children:g(s.value)}):null]})})]}),v!=="none"?t("ul",{className:"min-w-0 flex-1 space-y-1",children:l.map((e,n)=>c("li",{onMouseEnter:()=>r(n),onMouseLeave:()=>r(null),className:N("flex items-center gap-2.5 rounded-ctl px-2 py-1.5 text-[13px] transition-colors",a===n&&"bg-hover"),children:[t("span",{className:"size-2.5 shrink-0 rounded-[3px]",style:{background:e.color},"aria-hidden":!0}),t("span",{className:"min-w-0 flex-1 truncate text-body",children:e.label}),t("span",{className:"num font-medium text-text",children:m(e.value)}),t("span",{className:"num w-12 text-right text-[12px] text-muted",children:g(e.value)})]},e.id))}):null]})}export{_ as DonutChart};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Gauge — one number against its limit: occupancy, quota used, a target met.
|
|
4
|
+
*
|
|
5
|
+
* A half ring, drawn in SVG (no chart library, so it renders on the server
|
|
6
|
+
* too). The colour follows `thresholds` — calm below the first, amber past it,
|
|
7
|
+
* red past the second — and the number is always written in the middle,
|
|
8
|
+
* because a needle alone is not a reading.
|
|
9
|
+
*/
|
|
10
|
+
export declare function GaugeChart({ value, max, label, format, thresholds, invert, size, className, }: {
|
|
11
|
+
value: number;
|
|
12
|
+
max?: number;
|
|
13
|
+
label?: string;
|
|
14
|
+
format?: (value: number, max: number) => string;
|
|
15
|
+
/** Fractions of max where the colour turns warning, then danger. */
|
|
16
|
+
thresholds?: [number, number];
|
|
17
|
+
/** For measures where low is bad (battery, stock): the colours flip. */
|
|
18
|
+
invert?: boolean;
|
|
19
|
+
size?: number;
|
|
20
|
+
className?: string;
|
|
21
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as x from"react";import{cn as g}from"../../lib/utils.js";function M({value:n,max:s=100,label:i,format:m=(t,o)=>`${Math.round(t/o*100)}%`,thresholds:l=[.75,.9],invert:c=!1,size:p=200,className:v}){const t=Math.max(0,Math.min(1,s?n/s:0)),o=c?1-t:t,u=o>=l[1]?"var(--danger)":o>=l[0]?"var(--warning)":"var(--success)",h=Math.PI*80,f=x.useId().replace(/:/g,"");return a("div",{className:g("relative mx-auto",v),style:{width:p,height:p*.62},children:[a("svg",{viewBox:"0 0 200 124",className:"size-full overflow-visible",role:"img","aria-label":`${i??""} ${m(n,s)}`,children:[e("defs",{children:a("linearGradient",{id:`${f}-g`,x1:"0",x2:"1",children:[e("stop",{offset:"0",stopColor:u,stopOpacity:".55"}),e("stop",{offset:"1",stopColor:u})]})}),e("path",{d:"M20 110 A80 80 0 0 1 180 110",fill:"none",stroke:"var(--hover)",strokeWidth:"16",strokeLinecap:"round"}),l.map(d=>{const r=Math.PI*(1-(c?1-d:d));return e("line",{x1:100+64*Math.cos(r),y1:110-64*Math.sin(r),x2:100+70*Math.cos(r),y2:110-70*Math.sin(r),stroke:"var(--border2)",strokeWidth:"2",strokeLinecap:"round"},d)}),e("path",{d:"M20 110 A80 80 0 0 1 180 110",fill:"none",stroke:`url(#${f}-g)`,strokeWidth:"16",strokeLinecap:"round",strokeDasharray:h,strokeDashoffset:h*(1-t),style:{transition:"stroke-dashoffset 700ms var(--ease)"}})]}),a("div",{className:"absolute inset-x-0 bottom-0 text-center",children:[e("p",{className:"num disp text-[26px] font-semibold leading-none text-text",children:m(n,s)}),i?e("p",{className:"mt-1 text-[12px] text-muted",children:i}):null]})]})}export{M as GaugeChart};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Heatmap — a grid of rows × columns shaded by value: busy hours by weekday,
|
|
4
|
+
* occupancy by level and hour, sales by month and branch.
|
|
5
|
+
*
|
|
6
|
+
* One hue, light to dark (the sequential palette): magnitude only, never
|
|
7
|
+
* identity. Every cell carries its value in a tooltip and an accessible label,
|
|
8
|
+
* and the scale is printed under the grid so "dark" always means a number.
|
|
9
|
+
*/
|
|
10
|
+
export declare function Heatmap({ rows, columns, values, format, max, showColumnEvery, className, }: {
|
|
11
|
+
/** Row labels, top to bottom (e.g. weekdays). */
|
|
12
|
+
rows: string[];
|
|
13
|
+
/** Column labels, left to right (e.g. hours). */
|
|
14
|
+
columns: string[];
|
|
15
|
+
/** values[row][column] */
|
|
16
|
+
values: number[][];
|
|
17
|
+
format?: (v: number) => string;
|
|
18
|
+
/** Top of the scale; defaults to the largest value. */
|
|
19
|
+
max?: number;
|
|
20
|
+
/** Label every nth column so 24 hours stay readable. */
|
|
21
|
+
showColumnEvery?: number;
|
|
22
|
+
className?: string;
|
|
23
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as a,jsxs as r}from"react/jsx-runtime";import*as v from"react";import{cn as f}from"../../lib/utils.js";import{SEQUENTIAL as s}from"./palette.js";function b({rows:u,columns:m,values:o,format:t=n=>String(n),max:x,showColumnEvery:g=1,className:d}){const n=x??Math.max(1,...o.flat()),c=e=>e<=0?"var(--hover)":s[Math.min(s.length-1,Math.floor(e/n*(s.length-.001)))];return r("div",{className:f("overflow-x-auto",d),children:[r("div",{className:"inline-grid min-w-full gap-[3px]",style:{gridTemplateColumns:`auto repeat(${m.length}, minmax(14px, 1fr))`},children:[a("span",{}),m.map((e,p)=>a("span",{className:"num pb-1 text-center text-[10.5px] text-muted",children:p%g===0?e:""},e)),u.map((e,p)=>r(v.Fragment,{children:[a("span",{className:"pr-2 text-right text-[11.5px] leading-[18px] text-muted",children:e}),m.map((i,h)=>{const l=o[p]?.[h]??0;return a("span",{title:`${e} \xB7 ${i}: ${t(l)}`,"aria-label":`${e} ${i}: ${t(l)}`,className:"h-[18px] rounded-[4px] transition-transform hover:scale-110 hover:ring-2 hover:ring-primary/40",style:{background:c(l)}},i)})]},e))]}),r("div",{className:"mt-3 flex items-center justify-end gap-2 text-[11px] text-muted",children:[a("span",{className:"num",children:t(0)}),a("span",{className:"flex gap-[3px]",children:s.map(e=>a("span",{className:"h-2.5 w-5 rounded-[3px]",style:{background:e}},e))}),a("span",{className:"num",children:t(n)})]})]})}export{b as Heatmap};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Charts: Recharts (and plain SVG where a library is overkill) in the system's palette, card and tooltip. */
|
|
2
|
+
export * from "./bar-chart";
|
|
3
|
+
export * from "./bar-list";
|
|
4
|
+
export * from "./chart-card";
|
|
5
|
+
export * from "./donut-chart";
|
|
6
|
+
export * from "./gauge-chart";
|
|
7
|
+
export * from "./heatmap";
|
|
8
|
+
export * from "./line-chart";
|
|
9
|
+
export * from "./palette";
|
|
10
|
+
export * from "./trend-chart";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./bar-chart.js";export*from"./bar-list.js";export*from"./chart-card.js";export*from"./donut-chart.js";export*from"./gauge-chart.js";export*from"./heatmap.js";export*from"./line-chart.js";export*from"./palette.js";export*from"./trend-chart.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SeriesMeta } from "./chart-card";
|
|
3
|
+
export interface LineSeries extends SeriesMeta {
|
|
4
|
+
key: string;
|
|
5
|
+
/** Dashed and quieter: the comparison line (last week, target, forecast). */
|
|
6
|
+
dashed?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Lines — several measures over the same axis, or this period against the
|
|
10
|
+
* last one (mark the comparison `dashed`, it steps back so the current line
|
|
11
|
+
* leads). One y-axis, like every chart here. A `target` draws a labelled
|
|
12
|
+
* reference line instead of a fake series.
|
|
13
|
+
*/
|
|
14
|
+
export declare function LineChart({ data, xKey, series, format, target, curved, }: {
|
|
15
|
+
data: Record<string, string | number>[];
|
|
16
|
+
xKey: string;
|
|
17
|
+
series: LineSeries[];
|
|
18
|
+
format?: (v: number) => string;
|
|
19
|
+
target?: {
|
|
20
|
+
value: number;
|
|
21
|
+
label: string;
|
|
22
|
+
};
|
|
23
|
+
curved?: boolean;
|
|
24
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as i,jsxs as R}from"react/jsx-runtime";import{CartesianGrid as m,Line as y,LineChart as b,ReferenceLine as v,ResponsiveContainer as p,Tooltip as g,XAxis as L,YAxis as S}from"recharts";import{ChartTooltip as C}from"./chart-card.js";import{AXIS as t}from"./palette.js";function w({data:d,xKey:c,series:n,format:o=e=>String(e),target:r,curved:k=!0}){return i(p,{width:"100%",height:"100%",children:R(b,{data:d,margin:{top:8,right:8,bottom:0,left:-18},children:[i(m,{vertical:!1,stroke:t.grid}),i(L,{dataKey:c,tickLine:!1,axisLine:!1,tickMargin:8,tick:{fill:t.tick,fontSize:t.tickSize}}),i(S,{tickLine:!1,axisLine:!1,width:64,tickFormatter:e=>o(e),tick:{fill:t.tick,fontSize:t.tickSize}}),r?i(v,{y:r.value,stroke:"var(--border2)",strokeDasharray:"4 4",label:{value:r.label,position:"insideTopRight",fill:t.tick,fontSize:t.tickSize}}):null,i(g,{cursor:{stroke:"var(--border2)",strokeWidth:1},content:e=>{const{active:f,payload:l,label:u}=e;return!f||!l?.length?null:i(C,{label:u,rows:l.map(a=>{const s=n.find(h=>h.key===a.dataKey);return{id:a.dataKey,label:s?.label??a.dataKey,value:o(a.value),color:s?.color??t.tick}})})}}),n.map(e=>i(y,{type:k?"monotone":"linear",dataKey:e.key,name:e.label,stroke:e.color,strokeWidth:e.dashed?1.5:2.25,strokeDasharray:e.dashed?"5 4":void 0,strokeOpacity:e.dashed?.7:1,dot:!1,activeDot:e.dashed?!1:{r:4,strokeWidth:2,stroke:"var(--raised)"},isAnimationActive:!0,animationDuration:700},e.key))]})})}export{w as LineChart};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CHART PALETTE
|
|
3
|
+
*
|
|
4
|
+
* Validated, not chosen by eye. Both arrays below were run through the six
|
|
5
|
+
* checks (lightness band, chroma floor, CVD separation, normal-vision floor,
|
|
6
|
+
* contrast vs surface) against the light surface #f8f9fc *and* the dark
|
|
7
|
+
* surface #0b0f1e. One set clears both, which is why light and dark share it:
|
|
8
|
+
*
|
|
9
|
+
* lightness band PASS · chroma floor PASS
|
|
10
|
+
* CVD separation PASS (worst adjacent ΔE 9.2 deutan, 10.2 tritan)
|
|
11
|
+
* normal-vision PASS (worst adjacent ΔE 19.8)
|
|
12
|
+
* contrast PASS (all ≥ 3:1 on both surfaces)
|
|
13
|
+
*
|
|
14
|
+
* RULES
|
|
15
|
+
* 1. Hues are assigned in this fixed order and never cycled. A ninth series
|
|
16
|
+
* folds into "Other" or becomes small multiples — it is never a new hue.
|
|
17
|
+
* 2. Colour follows the entity, not its rank. Filtering a series out must not
|
|
18
|
+
* repaint the survivors, so callers key colour by series id, not by index
|
|
19
|
+
* into the filtered array.
|
|
20
|
+
* 3. Status colours (success / warning / danger) are reserved for state and
|
|
21
|
+
* are never reused as "series 4".
|
|
22
|
+
*/
|
|
23
|
+
export declare const SERIES: readonly ["#4f46e5", "#d97706", "#0891b2", "#db2777", "#047857", "#7c3aed", "#0284c7", "#a16207"];
|
|
24
|
+
/** Stable colour for a named series, independent of filtering or sort order. */
|
|
25
|
+
export declare function seriesColor(id: string, keys: readonly string[]): "#0284c7" | "#047857" | "#0891b2" | "#4f46e5" | "#7c3aed" | "#a16207" | "#d97706" | "#db2777";
|
|
26
|
+
/** Sequential — one hue, light to dark. Magnitude only, never identity. */
|
|
27
|
+
export declare const SEQUENTIAL: readonly ["#e0e7ff", "#c7d2fe", "#a5b4fc", "#818cf8", "#6366f1", "#4f46e5", "#4338ca"];
|
|
28
|
+
/** Diverging — two poles, neutral grey midpoint. Never a hue in the middle. */
|
|
29
|
+
export declare const DIVERGING: {
|
|
30
|
+
readonly negative: "#d97706";
|
|
31
|
+
readonly mid: "#9aa1bd";
|
|
32
|
+
readonly positive: "#0891b2";
|
|
33
|
+
};
|
|
34
|
+
/** Chart chrome reads from the same tokens as the rest of the product. */
|
|
35
|
+
export declare const AXIS: {
|
|
36
|
+
readonly grid: "var(--border)";
|
|
37
|
+
readonly tick: "var(--muted)";
|
|
38
|
+
readonly tickSize: 11;
|
|
39
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=["#4f46e5","#d97706","#0891b2","#db2777","#047857","#7c3aed","#0284c7","#a16207"];function n(o,c){const t=c.indexOf(o);return e[(t<0?0:t)%e.length]}const s=["#e0e7ff","#c7d2fe","#a5b4fc","#818cf8","#6366f1","#4f46e5","#4338ca"],r={negative:"#d97706",mid:"#9aa1bd",positive:"#0891b2"},a={grid:"var(--border)",tick:"var(--muted)",tickSize:11};export{a as AXIS,r as DIVERGING,s as SEQUENTIAL,e as SERIES,n as seriesColor};
|