@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
@@ -0,0 +1,31 @@
1
+ // src/MapControls/MapControls.manifest.ts
2
+ var MapControlsManifest = {
3
+ MapControls: {
4
+ description: "Engine-independent map navigation requests with supplied zoom and north-bearing readouts.",
5
+ props: {
6
+ label: { type: "string", default: "Map controls" },
7
+ zoom: {
8
+ type: "number",
9
+ description: "Supplied finite zoom within minZoom/maxZoom; null or missing is unknown. Readouts round to two decimals without changing the supplied value."
10
+ },
11
+ bearing: {
12
+ type: "number",
13
+ description: "Supplied clockwise degrees from north in [0,360). Null, missing or invalid values remain unknown. Display rounds to two decimals, so a bearing that rounds to 360 shows 0."
14
+ },
15
+ minZoom: { type: "number", default: 2 },
16
+ maxZoom: { type: "number", default: 20 },
17
+ onAction: {
18
+ type: "function",
19
+ description: "(action: MapAction) => void. Requests zoom-in, zoom-out, pan-north/east/south/west, reset-north or fit; no internal viewport change. Omission disables actions."
20
+ },
21
+ disabled: { type: "boolean", default: false },
22
+ className: { type: "string" }
23
+ },
24
+ composable_with: ["MapScale", "LayerControl", "MapLegend", "CoordinateInput", "AppShell"],
25
+ never_inside: ["Button"],
26
+ example: "<MapControls zoom={view.zoom} bearing={view.bearing} onAction={requestMapAction} />"
27
+ }
28
+ };
29
+ export {
30
+ MapControlsManifest
31
+ };
@@ -0,0 +1,7 @@
1
+ // src/MapControls/index.ts
2
+ import { MapControls } from "./MapControls.js";
3
+ import { MapControlsManifest } from "./MapControls.manifest.js";
4
+ export {
5
+ MapControls,
6
+ MapControlsManifest
7
+ };
@@ -0,0 +1,89 @@
1
+ "use client";
2
+
3
+ // src/MapLegend/MapLegend.tsx
4
+ import { forwardRef, useRef } from "react";
5
+ import { cva } from "class-variance-authority";
6
+ import clsx from "clsx";
7
+ import { joinIds, usePartIds } from "../_internal/fieldIds.js";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ var legendStyles = cva("flex min-w-0 flex-col gap-2u font-sans text-oprt-base text-oprt-text");
10
+ var symbolStyles = cva("block shrink-0 forced-colors:text-[CanvasText]", {
11
+ variants: {
12
+ kind: {
13
+ point: "h-1u w-1u bg-current forced-colors:border forced-colors:border-[CanvasText]",
14
+ line: "w-3u border-t-2 border-current",
15
+ area: "h-2u w-3u border-2 border-current"
16
+ },
17
+ variant: {
18
+ neutral: "text-oprt-text-dim",
19
+ success: "text-oprt-success",
20
+ warning: "text-oprt-warning",
21
+ error: "text-oprt-error",
22
+ info: "text-oprt-info",
23
+ accent: "text-oprt-accent"
24
+ },
25
+ pattern: { solid: "border-solid", dashed: "border-dashed" }
26
+ },
27
+ defaultVariants: { variant: "neutral", pattern: "solid" }
28
+ });
29
+ var kinds = { point: "Point", line: "Line", area: "Area" };
30
+ var MapLegend = forwardRef(
31
+ ({ label = "Map legend", items, className, id, "aria-labelledby": labelledBy, ...props }, ref) => {
32
+ const labelRef = useRef(null);
33
+ const ids = usePartIds(["label"], {
34
+ id,
35
+ readRendered: () => labelRef.current?.id.replace(/-label$/, "")
36
+ });
37
+ return /* @__PURE__ */ jsxs(
38
+ "div",
39
+ {
40
+ ...props,
41
+ id,
42
+ ref,
43
+ role: "group",
44
+ "aria-labelledby": joinIds(ids.label, labelledBy),
45
+ className: clsx(legendStyles(), className),
46
+ children: [
47
+ /* @__PURE__ */ jsx(
48
+ "h3",
49
+ {
50
+ ref: labelRef,
51
+ id: ids.label,
52
+ className: "m-0 min-w-0 font-medium uppercase tracking-oprt-sm oprt-wrap-anywhere",
53
+ children: label
54
+ }
55
+ ),
56
+ items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "m-0", children: "No legend items supplied." }) : /* @__PURE__ */ jsx("ul", { "aria-label": label, className: "m-0 flex min-w-0 list-none flex-col gap-2u p-0", children: items.map((item, index) => /* @__PURE__ */ jsxs("li", { className: "flex min-w-0 items-start gap-2u", children: [
57
+ /* @__PURE__ */ jsx(
58
+ "span",
59
+ {
60
+ "aria-hidden": "true",
61
+ className: "flex h-3u w-3u shrink-0 items-center justify-center",
62
+ children: /* @__PURE__ */ jsx(
63
+ "span",
64
+ {
65
+ className: symbolStyles({
66
+ kind: item.kind,
67
+ variant: item.variant ?? "neutral",
68
+ pattern: item.kind === "point" ? "solid" : item.pattern ?? "solid"
69
+ })
70
+ }
71
+ )
72
+ }
73
+ ),
74
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 oprt-wrap-anywhere", children: [
75
+ /* @__PURE__ */ jsx("p", { className: "m-0 font-medium", children: item.label }),
76
+ /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim", children: kinds[item.kind] }),
77
+ item.kind !== "point" && /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim", children: item.pattern === "dashed" ? "Dashed" : "Solid" }),
78
+ item.description && /* @__PURE__ */ jsx("p", { className: "m-0", children: item.description })
79
+ ] })
80
+ ] }, `${item.id}-${index}`)) })
81
+ ]
82
+ }
83
+ );
84
+ }
85
+ );
86
+ MapLegend.displayName = "MapLegend";
87
+ export {
88
+ MapLegend
89
+ };
@@ -0,0 +1,29 @@
1
+ // src/MapLegend/MapLegend.manifest.ts
2
+ var MapLegendManifest = {
3
+ MapLegend: {
4
+ description: "Text and shape map legend for supplied point, line and area meanings.",
5
+ props: {
6
+ label: { type: "string", default: "Map legend" },
7
+ items: {
8
+ type: "array",
9
+ required: true,
10
+ description: "Readonly MapLegendItem[]; labels/descriptions explain the supplied geometry. Variants use existing tokens; geometry kind and line/area pattern are always visible as text. Point symbols remain solid.",
11
+ items: {
12
+ id: "string",
13
+ label: "string",
14
+ kind: "point | line | area",
15
+ variant: "neutral | success | warning | error | info | accent (optional; neutral)",
16
+ pattern: "solid | dashed (optional; solid; applies to line/area)",
17
+ description: "string (optional)"
18
+ }
19
+ },
20
+ className: { type: "string" }
21
+ },
22
+ composable_with: ["LayerControl", "MapControls", "DescriptionList"],
23
+ never_inside: ["Button"],
24
+ example: '<MapLegend items={[{ id: "coverage", label: "Reported coverage", kind: "area", variant: "info", description: "Supplied model footprint" }]} />'
25
+ }
26
+ };
27
+ export {
28
+ MapLegendManifest
29
+ };
@@ -0,0 +1,7 @@
1
+ // src/MapLegend/index.ts
2
+ import { MapLegend } from "./MapLegend.js";
3
+ import { MapLegendManifest } from "./MapLegend.manifest.js";
4
+ export {
5
+ MapLegend,
6
+ MapLegendManifest
7
+ };
@@ -0,0 +1,96 @@
1
+ "use client";
2
+
3
+ // src/MapScale/MapScale.tsx
4
+ import { forwardRef, useRef } from "react";
5
+ import { useNumberFormatter } from "react-aria";
6
+ import { cva } from "class-variance-authority";
7
+ import clsx from "clsx";
8
+ import { devValidate } from "../_internal/devValidate.js";
9
+ import { joinIds, usePartIds } from "../_internal/fieldIds.js";
10
+ import { NumberText } from "../_internal/numberText.js";
11
+ import { useElementWidth } from "../_internal/useElementWidth.js";
12
+ import { MapScaleManifest } from "./MapScale.manifest.js";
13
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
+ var DISTANCE = { maximumSignificantDigits: 15 };
15
+ var scaleStyles = cva("flex min-w-0 flex-col gap-1u font-sans text-oprt-base text-oprt-text");
16
+ function scale(metersPerPixel, width, units) {
17
+ if (metersPerPixel === null || !Number.isFinite(metersPerPixel) || metersPerPixel <= 0 || !Number.isFinite(width) || width <= 0)
18
+ return null;
19
+ const meters = metersPerPixel * width;
20
+ if (!Number.isFinite(meters) || meters <= 0) return null;
21
+ const [factor, unit] = units === "imperial" ? meters >= 1609.344 ? [1609.344, "mi"] : [0.3048, "ft"] : meters >= 1e3 ? [1e3, "km"] : [1, "m"];
22
+ const bound = meters / factor, magnitude = 10 ** Math.floor(Math.log10(bound));
23
+ const distance = [5, 2, 1].map((multiple) => multiple * magnitude).find((candidate) => candidate <= bound);
24
+ if (!distance || !Number.isFinite(distance)) return null;
25
+ const pixels = distance * factor / metersPerPixel;
26
+ if (!Number.isFinite(pixels) || pixels <= 0 || pixels > width) return null;
27
+ return { pixels, distance, unit };
28
+ }
29
+ var MapScale = forwardRef((allProps, ref) => {
30
+ const {
31
+ label = "Map scale",
32
+ metersPerPixel = null,
33
+ maxWidth = 120,
34
+ units = "metric",
35
+ className,
36
+ id,
37
+ "aria-labelledby": labelledBy,
38
+ ...props
39
+ } = allProps;
40
+ if (process.env.NODE_ENV !== "production") {
41
+ devValidate("MapScale", MapScaleManifest.MapScale.props, { ...allProps });
42
+ }
43
+ const labelRef = useRef(null);
44
+ const ids = usePartIds(["label"], {
45
+ id,
46
+ readRendered: () => labelRef.current?.id.replace(/-label$/, "")
47
+ });
48
+ const format = useNumberFormatter(DISTANCE);
49
+ const available = useRef(null);
50
+ const measuredWidth = useElementWidth(available, {
51
+ initial: null
52
+ });
53
+ const value = Number.isFinite(maxWidth) && maxWidth > 0 ? scale(
54
+ metersPerPixel,
55
+ measuredWidth === null ? maxWidth : Math.min(maxWidth, measuredWidth),
56
+ units
57
+ ) : null;
58
+ return /* @__PURE__ */ jsxs(
59
+ "div",
60
+ {
61
+ ...props,
62
+ id,
63
+ ref,
64
+ role: "group",
65
+ "aria-labelledby": joinIds(ids.label, labelledBy),
66
+ className: clsx(scaleStyles(), className),
67
+ children: [
68
+ /* @__PURE__ */ jsx(
69
+ "h3",
70
+ {
71
+ ref: labelRef,
72
+ id: ids.label,
73
+ className: "m-0 min-w-0 font-medium uppercase tracking-oprt-sm oprt-wrap-anywhere",
74
+ children: label
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx("div", { ref: available, className: "min-w-0 w-full", children: value ? /* @__PURE__ */ jsxs(Fragment, { children: [
78
+ /* @__PURE__ */ jsx(
79
+ "span",
80
+ {
81
+ "data-testid": "scale-bar",
82
+ "aria-hidden": "true",
83
+ className: "block h-1u border-x-2 border-b-2 border-oprt-text forced-colors:border-[CanvasText]",
84
+ style: { width: value.pixels }
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx("p", { className: "m-0 font-mono tabular-nums", children: /* @__PURE__ */ jsx(NumberText, { value: format.format(value.distance), unit: value.unit }) })
88
+ ] }) : /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim", children: "Scale unavailable" }) })
89
+ ]
90
+ }
91
+ );
92
+ });
93
+ MapScale.displayName = "MapScale";
94
+ export {
95
+ MapScale
96
+ };
@@ -0,0 +1,31 @@
1
+ // src/MapScale/MapScale.manifest.ts
2
+ var MapScaleManifest = {
3
+ MapScale: {
4
+ description: "Bounded 1/2/5 ground-distance scale from a supplied local map resolution.",
5
+ props: {
6
+ label: { type: "string", default: "Map scale" },
7
+ metersPerPixel: {
8
+ type: "number",
9
+ description: "Positive finite local ground meters per CSS pixel. Missing/null/nonpositive/nonfinite values show Scale unavailable. Adapter owns projection and scale location."
10
+ },
11
+ maxWidth: {
12
+ type: "number",
13
+ default: 120,
14
+ description: "Positive finite maximum bar width in CSS pixels. Recomputes against narrower measured container width rather than shrinking a mislabeled bar."
15
+ },
16
+ units: {
17
+ type: "enum",
18
+ values: ["metric", "imperial"],
19
+ default: "metric",
20
+ description: "Metric uses m/km; imperial uses ft/mi. Both derive from the same supplied ground resolution."
21
+ },
22
+ className: { type: "string" }
23
+ },
24
+ composable_with: ["MapControls", "MapLegend", "AppShell"],
25
+ never_inside: ["Button"],
26
+ example: '<MapScale metersPerPixel={frame.metersPerPixel} units="metric" />'
27
+ }
28
+ };
29
+ export {
30
+ MapScaleManifest
31
+ };
@@ -0,0 +1,7 @@
1
+ // src/MapScale/index.ts
2
+ import { MapScale } from "./MapScale.js";
3
+ import { MapScaleManifest } from "./MapScale.manifest.js";
4
+ export {
5
+ MapScale,
6
+ MapScaleManifest
7
+ };
@@ -0,0 +1,113 @@
1
+ "use client";
2
+
3
+ // src/MediaFrame/MediaFrame.tsx
4
+ import { forwardRef, useRef } from "react";
5
+ import { useNumberFormatter } from "react-aria";
6
+ import { cva } from "class-variance-authority";
7
+ import clsx from "clsx";
8
+ import { Badge } from "../Badge/Badge.js";
9
+ import { devValidate } from "../_internal/devValidate.js";
10
+ import { joinIds, usePartIds } from "../_internal/fieldIds.js";
11
+ import { NumberText } from "../_internal/numberText.js";
12
+ import { formatUtcTimestamp, isValidTimestamp } from "../_internal/timestamp.js";
13
+ import { MediaFrameManifest } from "./MediaFrame.manifest.js";
14
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
+ var EXACT_NUMBER = { maximumSignificantDigits: 21 };
16
+ var frameStyles = cva(
17
+ "flex min-w-0 flex-col border border-oprt-border bg-oprt-surface-1 font-sans text-oprt-base normal-case text-oprt-text"
18
+ );
19
+ var MediaFrame = forwardRef((allProps, ref) => {
20
+ const {
21
+ label,
22
+ state,
23
+ capturedAt,
24
+ source,
25
+ latencyMs,
26
+ retained = false,
27
+ detail,
28
+ aspectRatio = 16 / 9,
29
+ children,
30
+ actions,
31
+ className,
32
+ id,
33
+ "aria-labelledby": labelledBy,
34
+ ...props
35
+ } = allProps;
36
+ if (process.env.NODE_ENV !== "production") {
37
+ devValidate("MediaFrame", MediaFrameManifest.MediaFrame.props, { ...allProps });
38
+ }
39
+ const labelRef = useRef(null);
40
+ const ids = usePartIds(["label"], {
41
+ id,
42
+ readRendered: () => labelRef.current?.id.replace(/-label$/, "")
43
+ });
44
+ const latency = useNumberFormatter(EXACT_NUMBER);
45
+ const valid = isValidTimestamp(capturedAt);
46
+ const shownTime = valid ? formatUtcTimestamp(capturedAt) : null;
47
+ const timestamp = valid ? new Date(capturedAt).toISOString() : null;
48
+ const unavailable = state === "unavailable" || state === "reconnecting";
49
+ const ratio = Number.isFinite(aspectRatio) && aspectRatio > 0 ? aspectRatio : 16 / 9;
50
+ return /* @__PURE__ */ jsxs(
51
+ "div",
52
+ {
53
+ ...props,
54
+ id,
55
+ ref,
56
+ role: "region",
57
+ "aria-labelledby": joinIds(ids.label, labelledBy),
58
+ className: clsx(frameStyles(), className),
59
+ children: [
60
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2u border-b border-oprt-border p-2u", children: [
61
+ /* @__PURE__ */ jsx(
62
+ "h3",
63
+ {
64
+ ref: labelRef,
65
+ id: ids.label,
66
+ className: "m-0 min-w-0 font-medium uppercase tracking-oprt-sm oprt-wrap-anywhere",
67
+ children: label
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx(Badge, { appearance: "text", variant: "neutral", children: state })
71
+ ] }),
72
+ /* @__PURE__ */ jsx(
73
+ "div",
74
+ {
75
+ className: "relative flex w-full min-w-0 items-center justify-center overflow-hidden bg-oprt-bg [&>canvas]:h-full [&>canvas]:w-full [&>canvas]:object-contain [&>img]:h-full [&>img]:w-full [&>img]:object-contain [&>video]:h-full [&>video]:w-full [&>video]:object-contain",
76
+ style: { aspectRatio: ratio === 16 / 9 ? "16 / 9" : String(ratio) },
77
+ children: children ?? /* @__PURE__ */ jsx("p", { className: "m-0 p-2u text-oprt-text-dim", children: "No media supplied." })
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1u border-t border-oprt-border p-2u", children: [
81
+ source && /* @__PURE__ */ jsxs("p", { className: "m-0 text-oprt-text-dim oprt-wrap-anywhere", children: [
82
+ "Source: ",
83
+ /* @__PURE__ */ jsx("span", { children: source })
84
+ ] }),
85
+ unavailable && /* @__PURE__ */ jsx("p", { className: "m-0", children: "Current frame unavailable." }),
86
+ retained && /* @__PURE__ */ jsx("p", { className: "m-0", children: "Retained frame \u2014 not current." }),
87
+ /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim oprt-wrap-anywhere", children: timestamp && shownTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
88
+ retained || unavailable ? "Last frame captured: " : "Captured: ",
89
+ /* @__PURE__ */ jsx("time", { className: "font-mono tabular-nums", dateTime: timestamp, children: shownTime })
90
+ ] }) : "Capture time unknown." }),
91
+ latencyMs !== void 0 && /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim", children: latencyMs !== null && Number.isFinite(latencyMs) && latencyMs >= 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
92
+ "Latency:",
93
+ " ",
94
+ /* @__PURE__ */ jsx(
95
+ NumberText,
96
+ {
97
+ value: latency.format(latencyMs + 0),
98
+ unit: "ms",
99
+ className: "font-mono tabular-nums"
100
+ }
101
+ )
102
+ ] }) : "Latency unknown." }),
103
+ detail && /* @__PURE__ */ jsx("p", { className: "m-0 oprt-wrap-anywhere", children: detail }),
104
+ actions && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1u", children: actions })
105
+ ] })
106
+ ]
107
+ }
108
+ );
109
+ });
110
+ MediaFrame.displayName = "MediaFrame";
111
+ export {
112
+ MediaFrame
113
+ };
@@ -0,0 +1,57 @@
1
+ // src/MediaFrame/MediaFrame.manifest.ts
2
+ var MediaFrameManifest = {
3
+ MediaFrame: {
4
+ description: "Named media surface with supplied freshness state, capture time and retained-frame disclosure.",
5
+ props: {
6
+ label: { type: "string", required: true },
7
+ state: {
8
+ type: "enum",
9
+ values: ["live", "delayed", "paused", "recorded", "reconnecting", "unavailable"],
10
+ required: true,
11
+ description: "Caller-supplied state. Reconnecting and unavailable always disclose that a current frame is unavailable."
12
+ },
13
+ capturedAt: {
14
+ type: "number",
15
+ required: true,
16
+ description: "Actual supplied frame capture time in epoch milliseconds, or null (fractional milliseconds allowed). Shown as YYYY-MM-DD HH:MM:SS UTC; the time element keeps the exact ISO instant in dateTime. Invalid dates and null display an unknown capture time."
17
+ },
18
+ source: {
19
+ type: "string",
20
+ description: "Readable source identity; does not initiate a connection."
21
+ },
22
+ latencyMs: {
23
+ type: "number",
24
+ description: "Supplied nonnegative latency in milliseconds, or null for unknown. Invalid values display unknown; omitted values are hidden."
25
+ },
26
+ retained: {
27
+ type: "boolean",
28
+ default: false,
29
+ description: "Explicitly labels imagery as a retained frame that is not current."
30
+ },
31
+ detail: {
32
+ type: "string",
33
+ description: "Persistent application explanation of the media state."
34
+ },
35
+ aspectRatio: {
36
+ type: "number",
37
+ default: 1.7777777777777777,
38
+ description: "Media width divided by height; defaults to 16/9. Nonpositive or nonfinite ratios fall back to 16/9."
39
+ },
40
+ children: {
41
+ type: "node",
42
+ description: "Application-owned media, image, canvas or fallback. Direct media children fit within the aspect-ratio surface without cropping."
43
+ },
44
+ actions: {
45
+ type: "node",
46
+ description: "Application-supplied accessible actions. Availability, permissions and outcomes remain with the caller."
47
+ },
48
+ className: { type: "string" }
49
+ },
50
+ composable_with: ["PlaybackControls", "Button", "AttachmentPreview", "Inspector"],
51
+ never_inside: ["Button"],
52
+ example: '<MediaFrame label="Pump camera" state="recorded" capturedAt={confirmedFrameTime} source="CAM-12" detail="Training footage"><video muted playsInline src={recordingUrl} /></MediaFrame>'
53
+ }
54
+ };
55
+ export {
56
+ MediaFrameManifest
57
+ };
@@ -0,0 +1,7 @@
1
+ // src/MediaFrame/index.ts
2
+ import { MediaFrame } from "./MediaFrame.js";
3
+ import { MediaFrameManifest } from "./MediaFrame.manifest.js";
4
+ export {
5
+ MediaFrame,
6
+ MediaFrameManifest
7
+ };
@@ -0,0 +1,113 @@
1
+ "use client";
2
+
3
+ // src/MultiSelect/MultiSelect.tsx
4
+ import { forwardRef, useRef, useState } from "react";
5
+ import { cva } from "class-variance-authority";
6
+ import clsx from "clsx";
7
+ import { Check } from "@oprt/icons";
8
+ import { joinIds, usePartIds } from "../_internal/fieldIds.js";
9
+ import { useMergedRefs } from "../_internal/mergeRefs.js";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ var styles = cva("m-0 min-w-0 border p-2u font-sans text-oprt-base normal-case text-oprt-text", {
12
+ variants: { invalid: { true: "border-oprt-error", false: "border-oprt-border" } },
13
+ defaultVariants: { invalid: false }
14
+ });
15
+ var MultiSelect = forwardRef(
16
+ ({
17
+ label,
18
+ options,
19
+ value,
20
+ defaultValue = [],
21
+ onValueChange,
22
+ name,
23
+ description,
24
+ error,
25
+ disabled = false,
26
+ className,
27
+ "aria-describedby": describedBy,
28
+ ...props
29
+ }, ref) => {
30
+ const fieldset = useRef(null);
31
+ const fieldsetRef = useMergedRefs(fieldset, ref);
32
+ const ids = usePartIds(["description", "error"], {
33
+ readRendered: () => fieldset.current?.getAttribute("data-oprt-ids")
34
+ });
35
+ const [local, setLocal] = useState(defaultValue);
36
+ const selected = value ?? local;
37
+ const descriptions = joinIds(describedBy, description && ids.description, error && ids.error);
38
+ return /* @__PURE__ */ jsxs(
39
+ "fieldset",
40
+ {
41
+ ...props,
42
+ ref: fieldsetRef,
43
+ "data-oprt-ids": ids.base,
44
+ disabled,
45
+ "aria-invalid": Boolean(error) || void 0,
46
+ "aria-describedby": descriptions,
47
+ className: clsx(styles({ invalid: Boolean(error) }), className),
48
+ children: [
49
+ /* @__PURE__ */ jsx("legend", { className: "min-w-0 px-1u oprt-wrap-anywhere text-oprt-base font-medium text-oprt-text", children: label }),
50
+ description && /* @__PURE__ */ jsx(
51
+ "p",
52
+ {
53
+ id: ids.description,
54
+ className: "m-0 mb-1u min-w-0 oprt-wrap-anywhere text-oprt-text-dim",
55
+ children: description
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2u", children: options.map((option) => /* @__PURE__ */ jsxs(
59
+ "label",
60
+ {
61
+ className: "m-0 inline-flex min-h-3u items-center gap-1u font-medium has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50",
62
+ children: [
63
+ /* @__PURE__ */ jsxs("span", { className: "relative inline-flex h-3u w-3u shrink-0", children: [
64
+ /* @__PURE__ */ jsx(
65
+ "input",
66
+ {
67
+ type: "checkbox",
68
+ name,
69
+ value: option.value,
70
+ checked: selected.includes(option.value),
71
+ disabled: disabled || option.disabled,
72
+ className: "peer m-0 h-3u w-3u appearance-none border border-oprt-border-control bg-oprt-surface-2 checked:border-oprt-accent focus-visible:outline-hidden focus-visible:border-oprt-border-focus focus-visible:shadow-oprt-focus",
73
+ onChange: (event) => {
74
+ if (disabled || option.disabled) return;
75
+ const next = event.target.checked ? [.../* @__PURE__ */ new Set([...selected, option.value])] : selected.filter((key) => key !== option.value);
76
+ if (value === void 0) setLocal(next);
77
+ onValueChange?.(next);
78
+ }
79
+ }
80
+ ),
81
+ /* @__PURE__ */ jsx(
82
+ Check,
83
+ {
84
+ size: 20,
85
+ className: "pointer-events-none absolute inset-0 m-auto hidden text-oprt-accent peer-checked:block"
86
+ }
87
+ )
88
+ ] }),
89
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 oprt-wrap-anywhere", children: option.label })
90
+ ]
91
+ },
92
+ option.value
93
+ )) }),
94
+ options.length === 0 && /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-text-dim", children: "No options available." }),
95
+ error && // A caller's error is an alert, as in a Field (MultiSelect-R2).
96
+ /* @__PURE__ */ jsx(
97
+ "p",
98
+ {
99
+ id: ids.error,
100
+ role: "alert",
101
+ className: "m-0 mt-1u min-w-0 oprt-wrap-anywhere text-oprt-error",
102
+ children: error
103
+ }
104
+ )
105
+ ]
106
+ }
107
+ );
108
+ }
109
+ );
110
+ MultiSelect.displayName = "MultiSelect";
111
+ export {
112
+ MultiSelect
113
+ };
@@ -0,0 +1,51 @@
1
+ // src/MultiSelect/MultiSelect.manifest.ts
2
+ var MultiSelectManifest = {
3
+ MultiSelect: {
4
+ description: "Native checkbox group with shared OPERATOR Check icons, stable values, labeled options, and explicit validation.",
5
+ props: {
6
+ label: {
7
+ type: "string",
8
+ required: true,
9
+ description: "Visible fieldset legend and accessible group name."
10
+ },
11
+ options: {
12
+ type: "array",
13
+ required: true,
14
+ description: "Unique stable values. Disabled options remain visible.",
15
+ items: {
16
+ value: "string (required, unique)",
17
+ label: "string (required)",
18
+ disabled: "boolean"
19
+ }
20
+ },
21
+ value: {
22
+ type: "array",
23
+ description: "Controlled selected values; values missing from options are preserved during changes."
24
+ },
25
+ defaultValue: {
26
+ type: "array",
27
+ description: "Initial values for uncontrolled selection. Defaults to an empty array."
28
+ },
29
+ onValueChange: {
30
+ type: "function",
31
+ description: "(values: string[]) => void. Controlled state only changes when the owner supplies new values."
32
+ },
33
+ name: {
34
+ type: "string",
35
+ description: "Native form name shared by selected checkboxes. FormData returns one entry per selected, enabled option."
36
+ },
37
+ disabled: { type: "boolean", default: false },
38
+ description: { type: "string" },
39
+ error: {
40
+ type: "string",
41
+ description: "Visible validation text; associated with the group and paired with aria-invalid."
42
+ }
43
+ },
44
+ composable_with: ["Card"],
45
+ never_inside: ["Button"],
46
+ example: '<MultiSelect label="Sensors" options={[{ value: "radar", label: "Radar" }, { value: "optical", label: "Optical" }]} value={sensors} onValueChange={setSensors} />'
47
+ }
48
+ };
49
+ export {
50
+ MultiSelectManifest
51
+ };
@@ -0,0 +1,7 @@
1
+ // src/MultiSelect/index.ts
2
+ import { MultiSelect } from "./MultiSelect.js";
3
+ import { MultiSelectManifest } from "./MultiSelect.manifest.js";
4
+ export {
5
+ MultiSelect,
6
+ MultiSelectManifest
7
+ };