@oprt/react 0.0.0-stage → 0.2.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 (266) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/ActionStatus/ActionStatus.js +104 -0
  4. package/dist/ActionStatus/ActionStatus.manifest.js +64 -0
  5. package/dist/ActionStatus/index.js +7 -0
  6. package/dist/Alert/Alert.js +86 -0
  7. package/dist/Alert/Alert.manifest.js +36 -0
  8. package/dist/Alert/index.js +7 -0
  9. package/dist/AppShell/AppShell.js +103 -0
  10. package/dist/AppShell/AppShell.manifest.js +66 -0
  11. package/dist/AppShell/index.js +9 -0
  12. package/dist/AttachmentPreview/AttachmentPreview.js +145 -0
  13. package/dist/AttachmentPreview/AttachmentPreview.manifest.js +42 -0
  14. package/dist/AttachmentPreview/index.js +9 -0
  15. package/dist/Avatar/Avatar.js +87 -0
  16. package/dist/Avatar/Avatar.manifest.js +25 -0
  17. package/dist/Avatar/index.js +7 -0
  18. package/dist/Badge/Badge.js +124 -0
  19. package/dist/Badge/Badge.manifest.js +41 -0
  20. package/dist/Badge/index.js +7 -0
  21. package/dist/Breadcrumb/Breadcrumb.js +64 -0
  22. package/dist/Breadcrumb/Breadcrumb.manifest.js +28 -0
  23. package/dist/Breadcrumb/index.js +7 -0
  24. package/dist/BulkActionBar/BulkActionBar.js +145 -0
  25. package/dist/BulkActionBar/BulkActionBar.manifest.js +46 -0
  26. package/dist/BulkActionBar/index.js +9 -0
  27. package/dist/BulkActionBar/selection.js +44 -0
  28. package/dist/BulkResults/BulkResults.js +269 -0
  29. package/dist/BulkResults/BulkResults.manifest.js +45 -0
  30. package/dist/BulkResults/index.js +7 -0
  31. package/dist/Button/Button.js +170 -0
  32. package/dist/Button/Button.manifest.js +36 -0
  33. package/dist/Button/index.js +7 -0
  34. package/dist/ButtonGroup/ButtonGroup.js +60 -0
  35. package/dist/ButtonGroup/ButtonGroup.manifest.js +22 -0
  36. package/dist/ButtonGroup/index.js +7 -0
  37. package/dist/Calendar/Calendar.js +106 -0
  38. package/dist/Calendar/Calendar.manifest.js +32 -0
  39. package/dist/Calendar/index.js +7 -0
  40. package/dist/Card/Card.js +70 -0
  41. package/dist/Card/Card.manifest.js +57 -0
  42. package/dist/Card/index.js +16 -0
  43. package/dist/Chart/Chart.js +1200 -0
  44. package/dist/Chart/Chart.manifest.js +110 -0
  45. package/dist/Chart/ChartControls.js +190 -0
  46. package/dist/Chart/geometry.js +217 -0
  47. package/dist/Chart/index.js +9 -0
  48. package/dist/Checkbox/Checkbox.js +166 -0
  49. package/dist/Checkbox/Checkbox.manifest.js +38 -0
  50. package/dist/Checkbox/index.js +7 -0
  51. package/dist/Collapsible/Collapsible.js +177 -0
  52. package/dist/Collapsible/Collapsible.manifest.js +54 -0
  53. package/dist/Collapsible/index.js +12 -0
  54. package/dist/CollectionState/CollectionState.js +68 -0
  55. package/dist/CollectionState/CollectionState.manifest.js +44 -0
  56. package/dist/CollectionState/index.js +7 -0
  57. package/dist/ComboBox/ComboBox.js +221 -0
  58. package/dist/ComboBox/ComboBox.manifest.js +87 -0
  59. package/dist/ComboBox/index.js +7 -0
  60. package/dist/CommandPalette/CommandPalette.js +276 -0
  61. package/dist/CommandPalette/CommandPalette.manifest.js +24 -0
  62. package/dist/CommandPalette/index.js +7 -0
  63. package/dist/ConfirmDialog/ConfirmDialog.js +84 -0
  64. package/dist/ConfirmDialog/ConfirmDialog.manifest.js +32 -0
  65. package/dist/ConfirmDialog/index.js +7 -0
  66. package/dist/ContextMenu/ContextMenu.js +192 -0
  67. package/dist/ContextMenu/ContextMenu.manifest.js +41 -0
  68. package/dist/ContextMenu/index.js +7 -0
  69. package/dist/CoordinateInput/CoordinateInput.js +141 -0
  70. package/dist/CoordinateInput/CoordinateInput.manifest.js +36 -0
  71. package/dist/CoordinateInput/index.js +9 -0
  72. package/dist/CopyButton/CopyButton.js +129 -0
  73. package/dist/CopyButton/CopyButton.manifest.js +35 -0
  74. package/dist/CopyButton/index.js +7 -0
  75. package/dist/DataGrid/DataGrid.js +459 -0
  76. package/dist/DataGrid/DataGrid.manifest.js +135 -0
  77. package/dist/DataGrid/PageControls.js +41 -0
  78. package/dist/DataGrid/index.js +9 -0
  79. package/dist/DataTable/DataTable.js +375 -0
  80. package/dist/DataTable/DataTable.manifest.js +86 -0
  81. package/dist/DataTable/index.js +9 -0
  82. package/dist/DataTable/sort.js +45 -0
  83. package/dist/DataTable/useScrollsSideways.js +61 -0
  84. package/dist/DataTable/useTableWindow.js +185 -0
  85. package/dist/DatePicker/DatePicker.js +187 -0
  86. package/dist/DatePicker/DatePicker.manifest.js +40 -0
  87. package/dist/DatePicker/index.js +7 -0
  88. package/dist/DateRangePicker/DateRangePicker.js +156 -0
  89. package/dist/DateRangePicker/DateRangePicker.manifest.js +41 -0
  90. package/dist/DateRangePicker/index.js +7 -0
  91. package/dist/DateTimePicker/DateTimePicker.js +213 -0
  92. package/dist/DateTimePicker/DateTimePicker.manifest.js +44 -0
  93. package/dist/DateTimePicker/index.js +7 -0
  94. package/dist/DescriptionList/DescriptionList.js +93 -0
  95. package/dist/DescriptionList/DescriptionList.manifest.js +40 -0
  96. package/dist/DescriptionList/index.js +9 -0
  97. package/dist/Dialog/Dialog.js +214 -0
  98. package/dist/Dialog/Dialog.manifest.js +31 -0
  99. package/dist/Dialog/index.js +7 -0
  100. package/dist/Divider/Divider.js +64 -0
  101. package/dist/Divider/Divider.manifest.js +21 -0
  102. package/dist/Divider/index.js +7 -0
  103. package/dist/DropdownMenu/DropdownMenu.js +170 -0
  104. package/dist/DropdownMenu/DropdownMenu.manifest.js +82 -0
  105. package/dist/DropdownMenu/index.js +16 -0
  106. package/dist/EntityPreview/EntityPreview.js +82 -0
  107. package/dist/EntityPreview/EntityPreview.manifest.js +43 -0
  108. package/dist/EntityPreview/index.js +7 -0
  109. package/dist/EventTimeline/EventTimeline.js +249 -0
  110. package/dist/EventTimeline/EventTimeline.manifest.js +57 -0
  111. package/dist/EventTimeline/index.js +7 -0
  112. package/dist/Field/Field.js +81 -0
  113. package/dist/Field/Field.manifest.js +32 -0
  114. package/dist/Field/index.js +9 -0
  115. package/dist/FileUpload/FileUpload.js +215 -0
  116. package/dist/FileUpload/FileUpload.manifest.js +48 -0
  117. package/dist/FileUpload/index.js +7 -0
  118. package/dist/FilterBar/FilterBar.js +173 -0
  119. package/dist/FilterBar/FilterBar.manifest.js +49 -0
  120. package/dist/FilterBar/index.js +7 -0
  121. package/dist/FormErrorSummary/FormErrorSummary.js +70 -0
  122. package/dist/FormErrorSummary/FormErrorSummary.manifest.js +29 -0
  123. package/dist/FormErrorSummary/index.js +9 -0
  124. package/dist/FormSection/FormSection.js +51 -0
  125. package/dist/FormSection/FormSection.manifest.js +30 -0
  126. package/dist/FormSection/index.js +7 -0
  127. package/dist/InlineEdit/InlineEdit.js +261 -0
  128. package/dist/InlineEdit/InlineEdit.manifest.js +40 -0
  129. package/dist/InlineEdit/index.js +7 -0
  130. package/dist/Input/Input.js +126 -0
  131. package/dist/Input/Input.manifest.js +49 -0
  132. package/dist/Input/index.js +7 -0
  133. package/dist/Inspector/Inspector.js +63 -0
  134. package/dist/Inspector/Inspector.manifest.js +35 -0
  135. package/dist/Inspector/index.js +7 -0
  136. package/dist/JobStatus/JobStatus.js +118 -0
  137. package/dist/JobStatus/JobStatus.manifest.js +53 -0
  138. package/dist/JobStatus/index.js +7 -0
  139. package/dist/LayerControl/LayerControl.js +199 -0
  140. package/dist/LayerControl/LayerControl.manifest.js +34 -0
  141. package/dist/LayerControl/index.js +7 -0
  142. package/dist/Link/Link.js +83 -0
  143. package/dist/Link/Link.manifest.js +37 -0
  144. package/dist/Link/index.js +7 -0
  145. package/dist/MapControls/MapControls.js +122 -0
  146. package/dist/MapControls/MapControls.manifest.js +31 -0
  147. package/dist/MapControls/index.js +7 -0
  148. package/dist/MapLegend/MapLegend.js +89 -0
  149. package/dist/MapLegend/MapLegend.manifest.js +29 -0
  150. package/dist/MapLegend/index.js +7 -0
  151. package/dist/MapScale/MapScale.js +96 -0
  152. package/dist/MapScale/MapScale.manifest.js +31 -0
  153. package/dist/MapScale/index.js +7 -0
  154. package/dist/MediaFrame/MediaFrame.js +113 -0
  155. package/dist/MediaFrame/MediaFrame.manifest.js +57 -0
  156. package/dist/MediaFrame/index.js +7 -0
  157. package/dist/MultiSelect/MultiSelect.js +113 -0
  158. package/dist/MultiSelect/MultiSelect.manifest.js +51 -0
  159. package/dist/MultiSelect/index.js +7 -0
  160. package/dist/NumberInput/NumberInput.js +210 -0
  161. package/dist/NumberInput/NumberInput.manifest.js +56 -0
  162. package/dist/NumberInput/index.js +7 -0
  163. package/dist/OperationalStatus/OperationalStatus.js +89 -0
  164. package/dist/OperationalStatus/OperationalStatus.manifest.js +39 -0
  165. package/dist/OperationalStatus/index.js +9 -0
  166. package/dist/PlaybackControls/PlaybackControls.js +289 -0
  167. package/dist/PlaybackControls/PlaybackControls.manifest.js +85 -0
  168. package/dist/PlaybackControls/index.js +7 -0
  169. package/dist/Popover/Popover.js +302 -0
  170. package/dist/Popover/Popover.manifest.js +50 -0
  171. package/dist/Popover/index.js +7 -0
  172. package/dist/Progress/Progress.js +132 -0
  173. package/dist/Progress/Progress.manifest.js +30 -0
  174. package/dist/Progress/index.js +7 -0
  175. package/dist/PropertyFilter/PropertyFilter.js +306 -0
  176. package/dist/PropertyFilter/PropertyFilter.manifest.js +32 -0
  177. package/dist/PropertyFilter/index.js +11 -0
  178. package/dist/PropertyFilter/tokenError.js +17 -0
  179. package/dist/RadioGroup/RadioGroup.js +143 -0
  180. package/dist/RadioGroup/RadioGroup.manifest.js +44 -0
  181. package/dist/RadioGroup/index.js +9 -0
  182. package/dist/Select/Select.js +219 -0
  183. package/dist/Select/Select.manifest.js +77 -0
  184. package/dist/Select/index.js +9 -0
  185. package/dist/Sidebar/Sidebar.js +146 -0
  186. package/dist/Sidebar/Sidebar.manifest.js +72 -0
  187. package/dist/Sidebar/index.js +18 -0
  188. package/dist/Skeleton/Skeleton.js +76 -0
  189. package/dist/Skeleton/Skeleton.manifest.js +30 -0
  190. package/dist/Skeleton/index.js +7 -0
  191. package/dist/Slider/Slider.js +246 -0
  192. package/dist/Slider/Slider.manifest.js +56 -0
  193. package/dist/Slider/index.js +7 -0
  194. package/dist/Sparkline/Sparkline.js +135 -0
  195. package/dist/Sparkline/Sparkline.manifest.js +37 -0
  196. package/dist/Sparkline/index.js +7 -0
  197. package/dist/SplitPane/SplitPane.js +316 -0
  198. package/dist/SplitPane/SplitPane.manifest.js +79 -0
  199. package/dist/SplitPane/index.js +7 -0
  200. package/dist/StatCard/StatCard.js +163 -0
  201. package/dist/StatCard/StatCard.manifest.js +45 -0
  202. package/dist/StatCard/index.js +7 -0
  203. package/dist/Tabs/Tabs.js +181 -0
  204. package/dist/Tabs/Tabs.manifest.js +72 -0
  205. package/dist/Tabs/index.js +16 -0
  206. package/dist/Tabs/useTabsIndicator.js +71 -0
  207. package/dist/Tabs/useTabsScroll.js +123 -0
  208. package/dist/TagGroup/TagGroup.js +142 -0
  209. package/dist/TagGroup/TagGroup.manifest.js +35 -0
  210. package/dist/TagGroup/index.js +7 -0
  211. package/dist/Textarea/Textarea.js +68 -0
  212. package/dist/Textarea/Textarea.manifest.js +25 -0
  213. package/dist/Textarea/index.js +7 -0
  214. package/dist/TimeField/TimeField.js +118 -0
  215. package/dist/TimeField/TimeField.manifest.js +42 -0
  216. package/dist/TimeField/index.js +7 -0
  217. package/dist/TimeRange/TimeRange.js +184 -0
  218. package/dist/TimeRange/TimeRange.manifest.js +48 -0
  219. package/dist/TimeRange/index.js +9 -0
  220. package/dist/Toast/Toast.js +188 -0
  221. package/dist/Toast/Toast.manifest.js +77 -0
  222. package/dist/Toast/index.js +9 -0
  223. package/dist/Toggle/Toggle.js +154 -0
  224. package/dist/Toggle/Toggle.manifest.js +54 -0
  225. package/dist/Toggle/index.js +7 -0
  226. package/dist/Toolbar/Toolbar.js +86 -0
  227. package/dist/Toolbar/Toolbar.manifest.js +70 -0
  228. package/dist/Toolbar/index.js +12 -0
  229. package/dist/Tooltip/Tooltip.js +123 -0
  230. package/dist/Tooltip/Tooltip.manifest.js +27 -0
  231. package/dist/Tooltip/index.js +7 -0
  232. package/dist/TreeView/TreeView.js +129 -0
  233. package/dist/TreeView/TreeView.manifest.js +56 -0
  234. package/dist/TreeView/index.js +7 -0
  235. package/dist/UploadQueue/UploadQueue.js +296 -0
  236. package/dist/UploadQueue/UploadQueue.manifest.js +34 -0
  237. package/dist/UploadQueue/index.js +7 -0
  238. package/dist/_internal/MotionPopover.js +113 -0
  239. package/dist/_internal/aria.js +40 -0
  240. package/dist/_internal/bytes.js +18 -0
  241. package/dist/_internal/controlStyles.js +26 -0
  242. package/dist/_internal/date.js +179 -0
  243. package/dist/_internal/devValidate.js +51 -0
  244. package/dist/_internal/fieldIds.js +50 -0
  245. package/dist/_internal/hydration.js +74 -0
  246. package/dist/_internal/manifest-entry.js +0 -0
  247. package/dist/_internal/mergeRefs.js +68 -0
  248. package/dist/_internal/motion.js +138 -0
  249. package/dist/_internal/navigationLandmark.js +13 -0
  250. package/dist/_internal/numberText.js +176 -0
  251. package/dist/_internal/overlay.js +53 -0
  252. package/dist/_internal/segmentField.js +125 -0
  253. package/dist/_internal/suggestions.js +20 -0
  254. package/dist/_internal/timestamp.js +25 -0
  255. package/dist/_internal/unavailable.js +13 -0
  256. package/dist/_internal/useActionFocus.js +27 -0
  257. package/dist/_internal/useElementWidth.js +37 -0
  258. package/dist/_internal/useIsMounted.js +18 -0
  259. package/dist/_internal/useIsomorphicLayoutEffect.js +8 -0
  260. package/dist/_internal/useRestoreFocusOnRemoval.js +57 -0
  261. package/dist/index.cjs +17831 -0
  262. package/dist/index.d.cts +2330 -0
  263. package/dist/index.d.ts +2330 -0
  264. package/dist/index.js +407 -0
  265. package/dist/version.js +8 -0
  266. package/package.json +80 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OPERATOR contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,106 @@
1
- # Temporary Holding Version
1
+ # @oprt/react
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
+ React components for operational interfaces: command, control and industrial software. Part of
4
+ the [OPERATOR design system](https://oprt.dev).
5
+
6
+ 75 component families, from Button and DataGrid to OperationalStatus, Inspector and MapControls,
7
+ with interactive behavior from React Aria. Every component is dark, square-cornered and keyboard
8
+ operable, and spells its status out instead of relying on color alone, so dense, fast-changing
9
+ screens stay readable.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ pnpm add @oprt/react @oprt/tokens
15
+ pnpm add -D @oprt/tailwind tailwindcss@^4.3.3
16
+ ```
17
+
18
+ React 18 or later and React DOM are peer dependencies. The components are styled with Tailwind
19
+ CSS 4 and the OPERATOR plugin. Set Tailwind up the way your framework does, then add the plugin
20
+ and the components to the stylesheet where Tailwind is imported:
21
+
22
+ ```css
23
+ /* app/globals.css */
24
+ @import "tailwindcss";
25
+ @plugin "@oprt/tailwind";
26
+ /* The components ship as compiled JavaScript, which Tailwind does not scan on its own. The path is
27
+ relative to this file; without it the components render unstyled. */
28
+ @source "../node_modules/@oprt/react/dist";
29
+ ```
30
+
31
+ Import the tokens once at the application root, before that stylesheet:
32
+
33
+ ```ts
34
+ import "@oprt/tokens";
35
+ import "./globals.css";
36
+ ```
37
+
38
+ Load the tokens from JavaScript or a `<link>`, not with an `@import` inside the Tailwind
39
+ stylesheet: the Tailwind CLI inlines an imported file without rewriting its font URLs, and the
40
+ bundled fonts would not load. Inside Tailwind Typography's `prose`, wrap components in an element
41
+ with the `not-prose` class.
42
+
43
+ ## Use
44
+
45
+ ```tsx
46
+ import { Badge, Button, Field, Input } from "@oprt/react";
47
+
48
+ export function Handover() {
49
+ return (
50
+ <form>
51
+ <Field label="Callsign" required>
52
+ <Input placeholder="RAVEN 2" />
53
+ </Field>
54
+ <Badge variant="warning">Stale</Badge>
55
+ <Button type="submit">Acknowledge</Button>
56
+ </form>
57
+ );
58
+ }
59
+ ```
60
+
61
+ Every component's page at [oprt.dev/docs/components](https://oprt.dev/docs/components) shows its
62
+ variants live, with its props, its accessibility behavior and its manifest entry. Six complete
63
+ working screens are at [oprt.dev](https://oprt.dev).
64
+
65
+ ## What's included
66
+
67
+ - **Actions and inputs:** Button, ButtonGroup, CopyButton, Field, Input, Textarea, NumberInput,
68
+ CoordinateInput, Checkbox, RadioGroup, Toggle, Slider, Select, ComboBox, MultiSelect, TagGroup,
69
+ InlineEdit, FormSection, FormErrorSummary
70
+ - **Dates and times:** Calendar, DatePicker, DateRangePicker, DateTimePicker, TimeField, TimeRange
71
+ - **Data:** DataTable, DataGrid, Chart, Sparkline, StatCard, EventTimeline, DescriptionList,
72
+ FilterBar, PropertyFilter
73
+ - **Status and feedback:** Badge, Alert, Toast, Progress, Skeleton, OperationalStatus,
74
+ ActionStatus, JobStatus, CollectionState
75
+ - **Bulk work and files:** BulkActionBar, BulkResults, FileUpload, UploadQueue, AttachmentPreview
76
+ - **Layout and navigation:** AppShell, Sidebar, SplitPane, Tabs, Breadcrumb, Toolbar, Collapsible,
77
+ TreeView, Card, Divider, Link, Avatar
78
+ - **Overlays and inspection:** Dialog, ConfirmDialog, Popover, Tooltip, DropdownMenu, ContextMenu,
79
+ CommandPalette, Inspector, EntityPreview
80
+ - **Maps and media:** MapControls, LayerControl, MapLegend, MapScale, MediaFrame, PlaybackControls
81
+
82
+ Motion is tactile and quick. Turn it off for one component with `motion="none"`; the system's
83
+ reduced-motion setting turns it off everywhere.
84
+
85
+ ## Server Components and bundle size
86
+
87
+ Each module is its own file, and only the modules that need the browser are marked
88
+ `"use client"`. An app pays only for what it imports, and a Server Component can import the
89
+ manifest entries and data helpers from the package root. ES modules and CommonJS are both
90
+ included.
91
+
92
+ ## For coding agents
93
+
94
+ Each family exports its manifest entry (`ButtonManifest`, `DataGridManifest` and so on). In
95
+ development, an invalid option value logs a structured `INVALID_PROP_VALUE` error with the valid
96
+ values and a suggestion; production builds leave it out. For the whole contract, give an agent
97
+ [`@oprt/manifest`](https://www.npmjs.com/package/@oprt/manifest)'s `components.json`,
98
+ or use [`@oprt/cli`](https://www.npmjs.com/package/@oprt/cli) to write the agent's
99
+ instructions and check its code. See [oprt.dev/docs/agents](https://oprt.dev/docs/agents).
100
+
101
+ To own the code instead of installing it, the CLI copies any component, with everything it
102
+ depends on, into your project: `npx @oprt/cli add button`.
103
+
104
+ ## License
105
+
106
+ MIT. The OPERATOR fonts in `@oprt/tokens` are under the SIL Open Font License 1.1.
@@ -0,0 +1,104 @@
1
+ "use client";
2
+
3
+ // src/ActionStatus/ActionStatus.tsx
4
+ import { forwardRef } from "react";
5
+ import { cva } from "class-variance-authority";
6
+ import clsx from "clsx";
7
+ import { Badge } from "../Badge/Badge.js";
8
+ import { Button } from "../Button/Button.js";
9
+ import { useActionFocus } from "../_internal/useActionFocus.js";
10
+ import { devValidate } from "../_internal/devValidate.js";
11
+ import { ActionStatusManifest } from "./ActionStatus.manifest.js";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ var statusStyles = cva(
14
+ "flex min-w-0 flex-col gap-2u border border-oprt-border p-2u font-sans text-oprt-base normal-case text-oprt-text outline-hidden focus-visible:shadow-oprt-focus"
15
+ );
16
+ var variants = {
17
+ submitted: "info",
18
+ accepted: "info",
19
+ rejected: "error",
20
+ "in-progress": "info",
21
+ complete: "success",
22
+ partial: "warning",
23
+ failed: "error",
24
+ timeout: "warning",
25
+ queued: "info",
26
+ running: "info",
27
+ "cancel-requested": "info",
28
+ canceled: "neutral"
29
+ };
30
+ function ActionStatusLine({
31
+ state,
32
+ label,
33
+ message,
34
+ requestId,
35
+ children
36
+ }) {
37
+ return /* @__PURE__ */ jsxs(
38
+ "div",
39
+ {
40
+ role: "status",
41
+ "aria-live": "polite",
42
+ "aria-atomic": "true",
43
+ className: "flex min-w-0 flex-col gap-1u",
44
+ children: [
45
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 oprt-wrap-anywhere font-medium uppercase tracking-oprt-caps", children: label }),
46
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Badge, { variant: variants[state], indicator: "dot", children: state }) }),
47
+ requestId && /* @__PURE__ */ jsxs("span", { className: "min-w-0 oprt-wrap-anywhere font-mono", children: [
48
+ "Request: ",
49
+ requestId
50
+ ] }),
51
+ message && /* @__PURE__ */ jsx("p", { className: "m-0 min-w-0 oprt-wrap-anywhere", children: message }),
52
+ children
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ var ActionStatus = forwardRef((allProps, ref) => {
58
+ const {
59
+ state,
60
+ label,
61
+ message,
62
+ requestId,
63
+ onRetry,
64
+ onCancel,
65
+ retryLabel = "Retry",
66
+ cancelLabel = "Cancel",
67
+ disabled = false,
68
+ className,
69
+ onFocusCapture,
70
+ onBlurCapture,
71
+ ...props
72
+ } = allProps;
73
+ const focus = useActionFocus(ref, { onFocusCapture, onBlurCapture });
74
+ if (process.env.NODE_ENV !== "production") {
75
+ devValidate("ActionStatus", ActionStatusManifest.ActionStatus.props, { ...allProps });
76
+ }
77
+ return (
78
+ // The result is a group named by its label, so the place focus moves to is announced by name,
79
+ // as JobStatus's region is. A role or name the caller gives wins.
80
+ /* @__PURE__ */ jsxs(
81
+ "div",
82
+ {
83
+ tabIndex: -1,
84
+ role: "group",
85
+ "aria-label": label,
86
+ ...props,
87
+ ...focus,
88
+ className: clsx(statusStyles(), className),
89
+ children: [
90
+ /* @__PURE__ */ jsx(ActionStatusLine, { state, label, message, requestId }),
91
+ (onRetry || onCancel) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1u", children: [
92
+ onRetry && /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", disabled, onClick: onRetry, children: retryLabel }),
93
+ onCancel && /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "sm", disabled, onClick: onCancel, children: cancelLabel })
94
+ ] })
95
+ ]
96
+ }
97
+ )
98
+ );
99
+ });
100
+ ActionStatus.displayName = "ActionStatus";
101
+ export {
102
+ ActionStatus,
103
+ ActionStatusLine
104
+ };
@@ -0,0 +1,64 @@
1
+ // src/ActionStatus/ActionStatus.manifest.ts
2
+ var ActionStatusManifest = {
3
+ ActionStatus: {
4
+ description: "Stateless authoritative action outcome display with optional application-supported recovery callbacks. When the focused recovery is withdrawn or disabled, focus moves to the result, a group named by its label. Long text wraps.",
5
+ props: {
6
+ state: {
7
+ type: "enum",
8
+ values: [
9
+ "submitted",
10
+ "accepted",
11
+ "rejected",
12
+ "in-progress",
13
+ "complete",
14
+ "partial",
15
+ "failed",
16
+ "timeout",
17
+ "queued",
18
+ "running",
19
+ "cancel-requested",
20
+ "canceled"
21
+ ],
22
+ required: true,
23
+ description: "Authoritative application-supplied lifecycle state. Timeout does not imply rejection or completion. A cancel request does not establish cancellation; a supplied complete result can still follow cancel-requested."
24
+ },
25
+ label: {
26
+ type: "string",
27
+ required: true
28
+ },
29
+ message: {
30
+ type: "string"
31
+ },
32
+ requestId: {
33
+ type: "string"
34
+ },
35
+ onRetry: {
36
+ type: "function",
37
+ description: "Render Retry only when retry is supported. Does not change state."
38
+ },
39
+ onCancel: {
40
+ type: "function",
41
+ description: "Render Cancel only when cancellation is supported. Does not change state."
42
+ },
43
+ retryLabel: {
44
+ type: "string",
45
+ default: "Retry"
46
+ },
47
+ cancelLabel: {
48
+ type: "string",
49
+ default: "Cancel"
50
+ },
51
+ disabled: {
52
+ type: "boolean",
53
+ default: false,
54
+ description: "Disables recovery actions without hiding supplied outcomes."
55
+ }
56
+ },
57
+ composable_with: ["Inspector", "Alert", "AppShell"],
58
+ never_inside: ["Button"],
59
+ example: '<ActionStatus state={result.state} label="Refresh source" message={result.message} requestId={result.id} onRetry={canRetry ? retry : undefined} />'
60
+ }
61
+ };
62
+ export {
63
+ ActionStatusManifest
64
+ };
@@ -0,0 +1,7 @@
1
+ // src/ActionStatus/index.ts
2
+ import { ActionStatus } from "./ActionStatus.js";
3
+ import { ActionStatusManifest } from "./ActionStatus.manifest.js";
4
+ export {
5
+ ActionStatus,
6
+ ActionStatusManifest
7
+ };
@@ -0,0 +1,86 @@
1
+ "use client";
2
+
3
+ // src/Alert/Alert.tsx
4
+ import { Info, CheckCircle, AlertTriangle, XCircle, X } from "@oprt/icons";
5
+ import { cva } from "class-variance-authority";
6
+ import { forwardRef } from "react";
7
+ import clsx from "clsx";
8
+ import { AlertManifest } from "./Alert.manifest.js";
9
+ import { devValidate } from "../_internal/devValidate.js";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ var ICONS = {
12
+ info: Info,
13
+ success: CheckCircle,
14
+ warning: AlertTriangle,
15
+ error: XCircle
16
+ };
17
+ var containerStyles = cva(
18
+ "flex gap-2u px-3u py-2u bg-oprt-surface-1 border border-oprt-border border-l-2 font-sans",
19
+ {
20
+ variants: {
21
+ variant: {
22
+ info: "border-l-oprt-info",
23
+ success: "border-l-oprt-success",
24
+ warning: "border-l-oprt-warning",
25
+ error: "border-l-oprt-error"
26
+ }
27
+ }
28
+ }
29
+ );
30
+ var accentStyles = cva("", {
31
+ variants: {
32
+ variant: {
33
+ info: "text-oprt-info",
34
+ success: "text-oprt-success",
35
+ warning: "text-oprt-warning",
36
+ error: "text-oprt-error"
37
+ }
38
+ }
39
+ });
40
+ var Alert = forwardRef((allProps, ref) => {
41
+ const {
42
+ className,
43
+ variant,
44
+ title,
45
+ dismissible = false,
46
+ onDismiss,
47
+ children,
48
+ ...props
49
+ } = allProps;
50
+ const role = variant === "error" || variant === "warning" ? "alert" : "status";
51
+ const Icon = ICONS[variant];
52
+ const hasBody = children != null && typeof children !== "boolean" && children !== "";
53
+ if (process.env.NODE_ENV !== "production") {
54
+ devValidate("Alert", AlertManifest.Alert.props, allProps);
55
+ }
56
+ return /* @__PURE__ */ jsxs("div", { ref, role, className: clsx(containerStyles({ variant }), className), ...props, children: [
57
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: clsx("shrink-0", accentStyles({ variant })), children: /* @__PURE__ */ jsx(Icon, { size: 16 }) }),
58
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1u oprt-wrap-anywhere", children: [
59
+ title && /* @__PURE__ */ jsx(
60
+ "p",
61
+ {
62
+ className: clsx(
63
+ "m-0 text-oprt-sm uppercase tracking-oprt-sm",
64
+ accentStyles({ variant })
65
+ ),
66
+ children: title
67
+ }
68
+ ),
69
+ hasBody && /* @__PURE__ */ jsx("div", { className: "text-oprt-base normal-case text-oprt-text", children })
70
+ ] }),
71
+ dismissible && /* @__PURE__ */ jsx(
72
+ "button",
73
+ {
74
+ type: "button",
75
+ "aria-label": "Dismiss",
76
+ onClick: onDismiss,
77
+ className: "inline-flex items-center justify-center shrink-0 h-oprt-sm w-3u border border-transparent text-oprt-text-dim transition-colors duration-oprt-fast hover:text-oprt-text focus-visible:border-oprt-border-focus focus-visible:shadow-oprt-focus focus-visible:outline-hidden",
78
+ children: /* @__PURE__ */ jsx(X, { size: 12 })
79
+ }
80
+ )
81
+ ] });
82
+ });
83
+ Alert.displayName = "Alert";
84
+ export {
85
+ Alert
86
+ };
@@ -0,0 +1,36 @@
1
+ // src/Alert/Alert.manifest.ts
2
+ var AlertManifest = {
3
+ Alert: {
4
+ description: "Inline status message with a severity icon, semantic left-edge accent, optional title, and optional dismiss control.",
5
+ props: {
6
+ variant: {
7
+ type: "enum",
8
+ values: ["info", "success", "warning", "error"],
9
+ required: true,
10
+ description: "Severity. Drives icon, accent color, and ARIA role (error/warning = alert, info/success = status)."
11
+ },
12
+ title: {
13
+ type: "string",
14
+ description: "Optional uppercase heading shown above the description."
15
+ },
16
+ dismissible: {
17
+ type: "boolean",
18
+ default: false,
19
+ description: "Render a trailing Dismiss button that calls onDismiss."
20
+ },
21
+ onDismiss: {
22
+ type: "function",
23
+ description: "Called when the Dismiss button is activated."
24
+ }
25
+ },
26
+ slots: {
27
+ children: { type: "any", required: false }
28
+ },
29
+ composable_with: ["Card", "CardBody"],
30
+ never_inside: ["Alert", "Button", "Badge"],
31
+ example: '<Alert variant="error" title="LINK LOST">Telemetry stream dropped.</Alert>'
32
+ }
33
+ };
34
+ export {
35
+ AlertManifest
36
+ };
@@ -0,0 +1,7 @@
1
+ // src/Alert/index.ts
2
+ import { Alert } from "./Alert.js";
3
+ import { AlertManifest } from "./Alert.manifest.js";
4
+ export {
5
+ Alert,
6
+ AlertManifest
7
+ };
@@ -0,0 +1,103 @@
1
+ "use client";
2
+
3
+ // src/AppShell/AppShell.tsx
4
+ import { forwardRef, useId } from "react";
5
+ import { cva } from "class-variance-authority";
6
+ import clsx from "clsx";
7
+ import { Badge } from "../Badge/Badge.js";
8
+ import { devValidate } from "../_internal/devValidate.js";
9
+ import { InsideNavigationLandmarkProvider } from "../_internal/navigationLandmark.js";
10
+ import { formatUtcTimestamp, isValidTimestamp } from "../_internal/timestamp.js";
11
+ import { AppShellManifest } from "./AppShell.manifest.js";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ var shellStyles = cva(
14
+ "@container flex w-full min-w-0 flex-col border border-oprt-border bg-oprt-surface-1 font-sans text-oprt-base normal-case text-oprt-text"
15
+ );
16
+ var connectionVariants = {
17
+ connected: "success",
18
+ connecting: "warning",
19
+ reconnecting: "warning",
20
+ offline: "warning",
21
+ unknown: "neutral"
22
+ };
23
+ function connectionVariant(connection) {
24
+ return Object.prototype.hasOwnProperty.call(connectionVariants, connection) ? connectionVariants[connection] : "neutral";
25
+ }
26
+ var AppShell = forwardRef(
27
+ ({
28
+ title = "Workspace",
29
+ identity,
30
+ mode = "live",
31
+ connection = "unknown",
32
+ time,
33
+ markings,
34
+ navigation,
35
+ toolbar,
36
+ footer,
37
+ children,
38
+ className,
39
+ ...props
40
+ }, ref) => {
41
+ const id = useId();
42
+ if (process.env.NODE_ENV !== "production") {
43
+ devValidate("AppShell", AppShellManifest.AppShell.props, { mode, connection });
44
+ }
45
+ const shown = isValidTimestamp(time) ? formatUtcTimestamp(time) : null;
46
+ const isoTime = isValidTimestamp(time) ? new Date(time).toISOString() : null;
47
+ const split = shown?.indexOf(" ") ?? -1;
48
+ return /* @__PURE__ */ jsxs(
49
+ "div",
50
+ {
51
+ ...props,
52
+ ref,
53
+ role: "region",
54
+ "aria-labelledby": id,
55
+ className: clsx(shellStyles(), className),
56
+ children: [
57
+ markings && /* @__PURE__ */ jsx("div", { className: "border-b border-oprt-border bg-oprt-surface-2 px-2u py-1u text-center font-medium uppercase tracking-oprt-caps oprt-wrap-anywhere", children: markings }),
58
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2u border-b border-oprt-border p-2u", children: [
59
+ /* @__PURE__ */ jsx(
60
+ "h2",
61
+ {
62
+ id,
63
+ className: "m-0 min-w-0 text-oprt-md font-medium uppercase tracking-oprt-caps oprt-wrap-anywhere",
64
+ children: title
65
+ }
66
+ ),
67
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2u", children: [
68
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 normal-case oprt-wrap-anywhere", children: identity }),
69
+ /* @__PURE__ */ jsx(Badge, { variant: mode === "live" ? "info" : "neutral", indicator: "dot", children: mode }),
70
+ /* @__PURE__ */ jsx(Badge, { variant: connectionVariant(connection), indicator: "dot", children: connection }),
71
+ isoTime && shown ? (
72
+ // The date and the time wrap apart; neither breaks inside, so "UTC" stays with the
73
+ // time.
74
+ /* @__PURE__ */ jsxs("time", { className: "font-mono", dateTime: isoTime, children: [
75
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: shown.slice(0, split) }),
76
+ " ",
77
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: shown.slice(split + 1) })
78
+ ] })
79
+ ) : /* @__PURE__ */ jsx("span", { children: "Time unknown" })
80
+ ] })
81
+ ] }),
82
+ toolbar && /* @__PURE__ */ jsx("div", { className: "border-b border-oprt-border p-2u", children: toolbar }),
83
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col @oprt-lg:flex-row", children: [
84
+ navigation && /* @__PURE__ */ jsx(
85
+ "nav",
86
+ {
87
+ "aria-label": `${title} navigation`,
88
+ className: "min-w-0 max-h-40u overflow-y-auto border-b border-oprt-border p-2u @oprt-lg:max-h-none @oprt-lg:basis-1/4 @oprt-lg:overflow-visible @oprt-lg:border-b-0 @oprt-lg:border-r",
89
+ children: /* @__PURE__ */ jsx(InsideNavigationLandmarkProvider, { value: true, children: navigation })
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 break-words p-2u", children })
93
+ ] }),
94
+ footer && /* @__PURE__ */ jsx("div", { className: "min-w-0 break-words border-t border-oprt-border p-2u", children: footer })
95
+ ]
96
+ }
97
+ );
98
+ }
99
+ );
100
+ AppShell.displayName = "AppShell";
101
+ export {
102
+ AppShell
103
+ };
@@ -0,0 +1,66 @@
1
+ // src/AppShell/AppShell.manifest.ts
2
+ var AppShellManifest = {
3
+ AppShell: {
4
+ description: "In-page operational workspace with explicit identity, mode, connection, UTC reference time, and caller-supplied markings.",
5
+ props: {
6
+ identity: {
7
+ type: "string",
8
+ required: true,
9
+ description: "Application-supplied user or role identity; displayed verbatim."
10
+ },
11
+ title: {
12
+ type: "string",
13
+ default: "Workspace"
14
+ },
15
+ mode: {
16
+ type: "enum",
17
+ values: ["live", "paused", "replay", "training"],
18
+ default: "live",
19
+ description: "Presentation context. Does not connect to services or freeze data itself."
20
+ },
21
+ connection: {
22
+ type: "enum",
23
+ values: ["connected", "connecting", "reconnecting", "offline", "unknown"],
24
+ default: "unknown"
25
+ },
26
+ time: {
27
+ type: "number",
28
+ description: "Supplied reference time in epoch milliseconds, shown as YYYY-MM-DD HH:MM:SS UTC. Missing, null or invalid renders Time unknown; no running clock."
29
+ },
30
+ markings: {
31
+ type: "node",
32
+ description: "Caller-supplied policy/training markings. No classification is inferred."
33
+ },
34
+ navigation: {
35
+ type: "node",
36
+ description: `Navigation slot, usually a Sidebar, before the content in reading order. Beside the content when the shell is at least 640px wide (the shell's own width, not the window's); above it when narrower, capped at about eight rows and scrolling inside its named navigation landmark. The slot is the one navigation landmark, named from the title ("<title> navigation"); a Sidebar inside it adds no landmark of its own.`
37
+ },
38
+ toolbar: {
39
+ type: "node",
40
+ description: "Toolbar slot under the header; it grows with a toolbar that wraps onto more rows."
41
+ },
42
+ footer: {
43
+ type: "node"
44
+ }
45
+ },
46
+ slots: {
47
+ children: {
48
+ type: "ReactNode",
49
+ required: true
50
+ }
51
+ },
52
+ composable_with: [
53
+ "Sidebar",
54
+ "Inspector",
55
+ "TreeView",
56
+ "OperationalStatus",
57
+ "TimeRange",
58
+ "DataGrid"
59
+ ],
60
+ never_inside: ["Button"],
61
+ example: '<AppShell identity="Exercise analyst" mode="training" connection="offline" markings="EXERCISE" time={referenceTime}><DataGrid columns={columns} data={rows} getRowId={(row) => row.id} /></AppShell>'
62
+ }
63
+ };
64
+ export {
65
+ AppShellManifest
66
+ };
@@ -0,0 +1,9 @@
1
+ // src/AppShell/index.ts
2
+ import {
3
+ AppShell
4
+ } from "./AppShell.js";
5
+ import { AppShellManifest } from "./AppShell.manifest.js";
6
+ export {
7
+ AppShell,
8
+ AppShellManifest
9
+ };