@waveinno/ui 0.0.0-stage → 0.1.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.
Files changed (178) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +5 -0
  3. package/README.md +64 -2
  4. package/dist/brand/waveinno-logo.svg +1 -0
  5. package/dist/components/brand/index.d.ts +3 -0
  6. package/dist/components/brand/index.js +1 -0
  7. package/dist/components/brand/logo.d.ts +89 -0
  8. package/dist/components/brand/logo.js +1 -0
  9. package/dist/components/brand/waveinno-logo.d.ts +52 -0
  10. package/dist/components/brand/waveinno-logo.js +1 -0
  11. package/dist/components/charts/bar-chart.d.ts +20 -0
  12. package/dist/components/charts/bar-chart.js +1 -0
  13. package/dist/components/charts/bar-list.d.ts +27 -0
  14. package/dist/components/charts/bar-list.js +1 -0
  15. package/dist/components/charts/chart-card.d.ts +32 -0
  16. package/dist/components/charts/chart-card.js +1 -0
  17. package/dist/components/charts/donut-chart.d.ts +27 -0
  18. package/dist/components/charts/donut-chart.js +1 -0
  19. package/dist/components/charts/gauge-chart.d.ts +21 -0
  20. package/dist/components/charts/gauge-chart.js +1 -0
  21. package/dist/components/charts/heatmap.d.ts +23 -0
  22. package/dist/components/charts/heatmap.js +1 -0
  23. package/dist/components/charts/index.d.ts +10 -0
  24. package/dist/components/charts/index.js +1 -0
  25. package/dist/components/charts/line-chart.d.ts +24 -0
  26. package/dist/components/charts/line-chart.js +1 -0
  27. package/dist/components/charts/palette.d.ts +39 -0
  28. package/dist/components/charts/palette.js +1 -0
  29. package/dist/components/charts/trend-chart.d.ts +22 -0
  30. package/dist/components/charts/trend-chart.js +1 -0
  31. package/dist/components/patterns/activity-feed.d.ts +28 -0
  32. package/dist/components/patterns/activity-feed.js +1 -0
  33. package/dist/components/patterns/data-table-cells.d.ts +39 -0
  34. package/dist/components/patterns/data-table-cells.js +1 -0
  35. package/dist/components/patterns/data-table-edit.d.ts +56 -0
  36. package/dist/components/patterns/data-table-edit.js +1 -0
  37. package/dist/components/patterns/data-table-filters.d.ts +84 -0
  38. package/dist/components/patterns/data-table-filters.js +1 -0
  39. package/dist/components/patterns/data-table.d.ts +76 -0
  40. package/dist/components/patterns/data-table.js +2 -0
  41. package/dist/components/patterns/index.d.ts +16 -0
  42. package/dist/components/patterns/index.js +1 -0
  43. package/dist/components/patterns/kanban.d.ts +28 -0
  44. package/dist/components/patterns/kanban.js +1 -0
  45. package/dist/components/patterns/kpi-card.d.ts +22 -0
  46. package/dist/components/patterns/kpi-card.js +1 -0
  47. package/dist/components/patterns/money.d.ts +28 -0
  48. package/dist/components/patterns/money.js +1 -0
  49. package/dist/components/patterns/page-header.d.ts +38 -0
  50. package/dist/components/patterns/page-header.js +1 -0
  51. package/dist/components/patterns/page-hero.d.ts +50 -0
  52. package/dist/components/patterns/page-hero.js +1 -0
  53. package/dist/components/patterns/page-shell.d.ts +27 -0
  54. package/dist/components/patterns/page-shell.js +1 -0
  55. package/dist/components/patterns/stat-card.d.ts +56 -0
  56. package/dist/components/patterns/stat-card.js +1 -0
  57. package/dist/components/patterns/states.d.ts +27 -0
  58. package/dist/components/patterns/states.js +1 -0
  59. package/dist/components/patterns/timeline.d.ts +100 -0
  60. package/dist/components/patterns/timeline.js +1 -0
  61. package/dist/components/ui/avatar.d.ts +37 -0
  62. package/dist/components/ui/avatar.js +1 -0
  63. package/dist/components/ui/badge.d.ts +41 -0
  64. package/dist/components/ui/badge.js +1 -0
  65. package/dist/components/ui/button.d.ts +25 -0
  66. package/dist/components/ui/button.js +1 -0
  67. package/dist/components/ui/calendar.d.ts +42 -0
  68. package/dist/components/ui/calendar.js +1 -0
  69. package/dist/components/ui/card.d.ts +11 -0
  70. package/dist/components/ui/card.js +1 -0
  71. package/dist/components/ui/checkbox.d.ts +3 -0
  72. package/dist/components/ui/checkbox.js +1 -0
  73. package/dist/components/ui/combobox.d.ts +47 -0
  74. package/dist/components/ui/combobox.js +1 -0
  75. package/dist/components/ui/confirm-dialog.d.ts +34 -0
  76. package/dist/components/ui/confirm-dialog.js +1 -0
  77. package/dist/components/ui/date-picker.d.ts +80 -0
  78. package/dist/components/ui/date-picker.js +1 -0
  79. package/dist/components/ui/dialog.d.ts +54 -0
  80. package/dist/components/ui/dialog.js +1 -0
  81. package/dist/components/ui/dropdown-menu.d.ts +44 -0
  82. package/dist/components/ui/dropdown-menu.js +1 -0
  83. package/dist/components/ui/form-field.d.ts +27 -0
  84. package/dist/components/ui/form-field.js +1 -0
  85. package/dist/components/ui/index.d.ts +26 -0
  86. package/dist/components/ui/index.js +1 -0
  87. package/dist/components/ui/input.d.ts +21 -0
  88. package/dist/components/ui/input.js +1 -0
  89. package/dist/components/ui/label.d.ts +5 -0
  90. package/dist/components/ui/label.js +1 -0
  91. package/dist/components/ui/popover.d.ts +22 -0
  92. package/dist/components/ui/popover.js +1 -0
  93. package/dist/components/ui/progress.d.ts +43 -0
  94. package/dist/components/ui/progress.js +1 -0
  95. package/dist/components/ui/segmented.d.ts +42 -0
  96. package/dist/components/ui/segmented.js +1 -0
  97. package/dist/components/ui/select.d.ts +10 -0
  98. package/dist/components/ui/select.js +1 -0
  99. package/dist/components/ui/separator.d.ts +3 -0
  100. package/dist/components/ui/separator.js +1 -0
  101. package/dist/components/ui/sheet.d.ts +19 -0
  102. package/dist/components/ui/sheet.js +1 -0
  103. package/dist/components/ui/skeleton.d.ts +10 -0
  104. package/dist/components/ui/skeleton.js +1 -0
  105. package/dist/components/ui/switch.d.ts +3 -0
  106. package/dist/components/ui/switch.js +1 -0
  107. package/dist/components/ui/tabs.d.ts +19 -0
  108. package/dist/components/ui/tabs.js +1 -0
  109. package/dist/components/ui/time-picker.d.ts +52 -0
  110. package/dist/components/ui/time-picker.js +1 -0
  111. package/dist/components/ui/tooltip.d.ts +13 -0
  112. package/dist/components/ui/tooltip.js +1 -0
  113. package/dist/hooks/index.d.ts +4 -0
  114. package/dist/hooks/index.js +1 -0
  115. package/dist/hooks/use-hotkey.d.ts +16 -0
  116. package/dist/hooks/use-hotkey.js +1 -0
  117. package/dist/hooks/use-media-query.d.ts +4 -0
  118. package/dist/hooks/use-media-query.js +1 -0
  119. package/dist/hooks/use-mounted.d.ts +2 -0
  120. package/dist/hooks/use-mounted.js +1 -0
  121. package/dist/index.d.ts +17 -0
  122. package/dist/index.js +1 -0
  123. package/dist/lib/boot-script.d.ts +15 -0
  124. package/dist/lib/boot-script.js +12 -0
  125. package/dist/lib/currency.d.ts +55 -0
  126. package/dist/lib/currency.js +1 -0
  127. package/dist/lib/format.d.ts +28 -0
  128. package/dist/lib/format.js +1 -0
  129. package/dist/lib/index.d.ts +5 -0
  130. package/dist/lib/index.js +1 -0
  131. package/dist/lib/utils.d.ts +7 -0
  132. package/dist/lib/utils.js +1 -0
  133. package/dist/shell/app-shell.d.ts +18 -0
  134. package/dist/shell/app-shell.js +1 -0
  135. package/dist/shell/app-switcher.d.ts +9 -0
  136. package/dist/shell/app-switcher.js +1 -0
  137. package/dist/shell/appearance-controls.d.ts +13 -0
  138. package/dist/shell/appearance-controls.js +1 -0
  139. package/dist/shell/command-palette.d.ts +9 -0
  140. package/dist/shell/command-palette.js +1 -0
  141. package/dist/shell/config.d.ts +66 -0
  142. package/dist/shell/config.js +1 -0
  143. package/dist/shell/icon-rail.d.ts +2 -0
  144. package/dist/shell/icon-rail.js +1 -0
  145. package/dist/shell/index.d.ts +7 -0
  146. package/dist/shell/index.js +1 -0
  147. package/dist/shell/mobile-nav.d.ts +7 -0
  148. package/dist/shell/mobile-nav.js +1 -0
  149. package/dist/shell/module-sidebar.d.ts +9 -0
  150. package/dist/shell/module-sidebar.js +1 -0
  151. package/dist/shell/notifications.d.ts +5 -0
  152. package/dist/shell/notifications.js +1 -0
  153. package/dist/shell/placeholder-screen.d.ts +11 -0
  154. package/dist/shell/placeholder-screen.js +1 -0
  155. package/dist/shell/record-drawer.d.ts +32 -0
  156. package/dist/shell/record-drawer.js +1 -0
  157. package/dist/shell/registry.d.ts +24 -0
  158. package/dist/shell/registry.js +1 -0
  159. package/dist/shell/topbar.d.ts +9 -0
  160. package/dist/shell/topbar.js +1 -0
  161. package/dist/shell/use-active.d.ts +21 -0
  162. package/dist/shell/use-active.js +1 -0
  163. package/dist/shell/user-menu.d.ts +5 -0
  164. package/dist/shell/user-menu.js +1 -0
  165. package/dist/store/app-store.d.ts +10 -0
  166. package/dist/store/app-store.js +1 -0
  167. package/dist/store/drawer-store.d.ts +22 -0
  168. package/dist/store/drawer-store.js +1 -0
  169. package/dist/store/index.d.ts +5 -0
  170. package/dist/store/index.js +1 -0
  171. package/dist/store/settings-store.d.ts +22 -0
  172. package/dist/store/settings-store.js +1 -0
  173. package/dist/store/ui-store.d.ts +28 -0
  174. package/dist/store/ui-store.js +1 -0
  175. package/dist/styles.css +658 -0
  176. package/dist/types.d.ts +140 -0
  177. package/dist/types.js +0 -0
  178. package/package.json +98 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
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.0 — 2026-10-02
10
+
11
+ First release on npm, as compiled JavaScript (one module per file, `"use client"` kept per module) with type
12
+ definitions; no source or source maps are published.
13
+
14
+ - **Tokens** in `@waveinno/ui/styles.css`: light and dark, three densities, motion that stops for reduced motion.
15
+ - **Brand**: official `WaveinnoLogo` and `WaveinnoSymbol` (from brand/waveinno-logo.svg), `WaveMark` app icon in seven
16
+ tones drawn from the logo colours, squircle or round, flat or 3D, with shine / float / pulse / flip motion;
17
+ `PoweredBy` signature (inline or floating, like WAVEMAP's), `Watermark`; logo file at `@waveinno/ui/brand/`.
18
+ - **Primitives**: Button (primary, secondary, ghost, subtle, danger, link; gradient, glow, dark, outline, elevated,
19
+ glass, white; pill shape, xl size), Badge (soft, solid, outline, dot, gradient, live), Input and Textarea with
20
+ error / warning / success states and leading / trailing slots, FormField, Select, searchable Combobox, Checkbox,
21
+ Switch, Segmented (pill, solid, outline, glass, sliding thumb, three sizes), Tabs (underline, pill, solid, enclosed,
22
+ sliding indicator), Calendar, DatePicker, DateTimePicker, DateRangePicker with presets, TimePicker (12/24 h),
23
+ Dialog (floating drawer that widens or goes full width; icon and eyebrow header; frosted footer), Sheet,
24
+ ConfirmDialog (item preview, type-to-confirm), DropdownMenu (rich items, account header, glass and dark), Popover
25
+ (arrow, glass, dark, brand), Tooltip, Progress (bar, gradient, striped, segmented, indeterminate) and ProgressRing,
26
+ Avatar (name colours, status, verified, gradient ring, square), Skeleton.
27
+ - **Patterns**: DataTable with advanced filters (text, select, number, date; all / any; chips; saved in views),
28
+ search, sort, columns, pinning, CSV export, five looks (default, striped, bordered, cards, minimal), inline cell
29
+ editing with validation, bulk edit and bulk delete, sticky action column; UserCell and RowActions; PageHero;
30
+ PageHeader; StatCard (icon, spark, target, gradient, comparison) and KpiCard; Money; ActivityFeed (list, cards,
31
+ compact); ActivityTimeline; ChangeHistory (field diffs); ChangeNotes (threaded, replies); Note (tones, outline,
32
+ gradient); Kanban; empty, error and loading states.
33
+ - **Charts**: TrendChart, BarChart, LineChart (comparison and target), DonutChart, GaugeChart, Heatmap, BarList,
34
+ ChartCard and a validated palette.
35
+ - **Shell**: AppShell (rail → panel → content → drawer, ⌘K), theme and density controls, record drawer.
package/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright (c) 2026 WAVEINNO. All rights reserved.
2
+
3
+ This package is published for use in WAVEINNO products and by parties WAVEINNO
4
+ has authorised. No licence to copy, modify or redistribute it is granted
5
+ without written permission from WAVEINNO (info@waveinno.com).
package/README.md CHANGED
@@ -1,3 +1,65 @@
1
- # Temporary Holding Version
1
+ # @waveinno/ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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,3 @@
1
+ /** Brand: the WAVEINNO mark and product logos. */
2
+ export * from "./logo";
3
+ export * from "./waveinno-logo";
@@ -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,27 @@
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
+ */
10
+ export interface DonutDatum {
11
+ id: string;
12
+ label: string;
13
+ value: number;
14
+ color?: string;
15
+ }
16
+ export declare function DonutChart({ data, format, centerLabel, centerValue, maxSlices, otherLabel, height, legend, className, }: {
17
+ data: DonutDatum[];
18
+ format?: (v: number) => string;
19
+ centerLabel?: string;
20
+ /** Shown in the hole; defaults to the formatted total. */
21
+ centerValue?: React.ReactNode;
22
+ maxSlices?: number;
23
+ otherLabel?: string;
24
+ height?: number;
25
+ legend?: "right" | "bottom" | "none";
26
+ className?: string;
27
+ }): React.JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as u}from"react/jsx-runtime";import*as f from"react";import{Cell as D,Pie as M,PieChart as A,ResponsiveContainer as E,Tooltip as L}from"recharts";import{cn as y}from"../../lib/utils.js";import{ChartTooltip as P}from"./chart-card.js";import{SERIES as N}from"./palette.js";function K({data:g,format:c=l=>l.toLocaleString(),centerLabel:w="Total",centerValue:k,maxSlices:v=6,otherLabel:h="Other",height:R=220,legend:b="right",className:C}){const[l,m]=f.useState(null),o=f.useMemo(()=>{const e=[...g].sort((i,r)=>r.value-i.value),n=e.slice(0,v-(e.length>v?1:0)),d=e.slice(n.length),a=n.map((i,r)=>({...i,color:i.color??N[r%N.length]}));return d.length&&a.push({id:"__other",label:h,value:d.reduce((i,r)=>i+r.value,0),color:"var(--border2)"}),a},[g,v,h]),p=o.reduce((e,n)=>e+n.value,0),x=e=>p?`${(e/p*100).toFixed(e/p<.1?1:0)}%`:"0%",s=l!==null?o[l]:null;return u("div",{className:y("flex gap-5",b==="bottom"?"flex-col":"flex-col sm:flex-row sm:items-center",C),children:[u("div",{className:"relative mx-auto aspect-square w-full max-w-[220px] shrink-0",style:{height:R},children:[t(E,{width:"100%",height:"100%",children:u(A,{children:[t(L,{content:e=>{const{active:n,payload:d}=e,a=d?.[0]?.payload;return!n||!a?null:t(P,{rows:[{id:a.id,label:a.label,value:`${c(a.value)} \xB7 ${x(a.value)}`,color:a.color}]})}}),t(M,{data:o,dataKey:"value",nameKey:"label",innerRadius:"68%",outerRadius:"92%",paddingAngle:o.length>1?2:0,cornerRadius:4,stroke:"var(--raised)",strokeWidth:2,onMouseEnter:(e,n)=>m(n),onMouseLeave:()=>m(null),isAnimationActive:!0,animationDuration:700,children:o.map((e,n)=>t(D,{fill:e.color,fillOpacity:l===null||l===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:u("div",{children:[t("p",{className:"text-[11px] font-medium uppercase tracking-[0.06em] text-muted",children:s?s.label:w}),t("p",{className:"num disp mt-0.5 text-[20px] font-semibold leading-none text-text",children:s?c(s.value):k??c(p)}),s?t("p",{className:"num mt-1 text-[11.5px] text-muted",children:x(s.value)}):null]})})]}),b!=="none"?t("ul",{className:"min-w-0 flex-1 space-y-1",children:o.map((e,n)=>u("li",{onMouseEnter:()=>m(n),onMouseLeave:()=>m(null),className:y("flex items-center gap-2.5 rounded-ctl px-2 py-1.5 text-[13px] transition-colors",l===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:c(e.value)}),t("span",{className:"num w-12 text-right text-[12px] text-muted",children:x(e.value)})]},e.id))}):null]})}export{K 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};