@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,110 @@
1
+ // src/Chart/Chart.manifest.ts
2
+ var ChartManifest = {
3
+ Chart: {
4
+ description: "Native SVG charts with stable series identity and exact data tables. Line, area, and bar support shared pointer/keyboard readouts and an optional controlled observation window.",
5
+ props: {
6
+ label: {
7
+ type: "string",
8
+ required: true,
9
+ description: "Visible chart heading and accessible graphic name."
10
+ },
11
+ series: {
12
+ type: "array",
13
+ required: true,
14
+ description: "Readonly ChartSeries[] with unique stable IDs. Points are { x: number, y: number | null, label?: string }; null and non-finite coordinates are missing. Line/area preserve authored order; use ascending x. Heatmap requires unique x within each series.",
15
+ items: {
16
+ id: "string (unique, stable)",
17
+ label: "string",
18
+ data: "readonly ChartPoint[]",
19
+ color: "1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 (optional categorical token)"
20
+ }
21
+ },
22
+ variant: {
23
+ type: "enum",
24
+ values: ["line", "area", "bar", "scatter", "histogram", "heatmap"],
25
+ default: "line"
26
+ },
27
+ fill: {
28
+ type: "enum",
29
+ values: ["solid", "hatched"],
30
+ default: "solid",
31
+ description: "Area and bar fill treatment. Hatching adds texture while outlines carry series color and measurement."
32
+ },
33
+ description: {
34
+ type: "string",
35
+ description: "Visible supporting context, also included in the graphic description."
36
+ },
37
+ xLabel: {
38
+ type: "string",
39
+ description: "X axis label. Defaults to Sample, or Value for histograms."
40
+ },
41
+ xUnit: { type: "string", description: "X axis unit. Histogram x values use unit instead." },
42
+ yLabel: {
43
+ type: "string",
44
+ description: "Y axis label. Defaults to Value, or Count for histograms."
45
+ },
46
+ unit: {
47
+ type: "string",
48
+ description: "Measured value unit; shown on axes, thresholds, and the heatmap scale."
49
+ },
50
+ formatX: {
51
+ type: "function",
52
+ description: '(finiteX: number) => string. Formats x tick labels, the full start and end of the window in the line under the plot, and sample positions when no authored point label exists. For a time axis, return YYYY-MM-DD HH:MM:SS and set xUnit="UTC". Histogram bin bounds remain numeric.'
53
+ },
54
+ hiddenSeries: {
55
+ type: "array",
56
+ description: "Controlled hidden series IDs. Omit for internal visibility state. Hidden series are excluded from scales; raw data inspection still includes them."
57
+ },
58
+ onHiddenSeriesChange: {
59
+ type: "function",
60
+ description: "(ids: string[]) => void. Reports the requested hidden IDs; supplied hiddenSeries remains controlled."
61
+ },
62
+ disabled: {
63
+ type: "boolean",
64
+ default: false,
65
+ description: "Disables legend and range changes. Pointer/keyboard inspection and View data remain available."
66
+ },
67
+ rangeSelection: {
68
+ type: "boolean",
69
+ default: false,
70
+ description: "Shows a miniature overview with draggable and keyboard-operable start/end handles for line, area, and bar. Needs a non-zero x domain and at least one finite sample coordinate. Other variants ignore it."
71
+ },
72
+ xDomain: {
73
+ type: "node",
74
+ description: "Optional ChartRange { start, end } defining the full observation bounds for line/area/bar, including periods without measurements. Defaults to the extent of supplied x values. Pass snapshot bounds when linking time controls."
75
+ },
76
+ range: {
77
+ type: "node",
78
+ description: "Controlled ChartRange { start: number, end: number } in x units. Filters line/area/bar samples inclusively. Overlapping bounds clamp to the full domain; invalid or reversed bounds use it in full. Valid disjoint controlled ranges stay empty. Omit for internal range state. Supply full history for the overview."
79
+ },
80
+ onRangeChange: {
81
+ type: "function",
82
+ description: "(range: ChartRange) => void. Reports requested x bounds from range handles or reset. Supplied range remains controlled. Keyboard steps span 0.1% of the full domain; handles do not snap to observations."
83
+ },
84
+ cursor: {
85
+ type: "number",
86
+ description: "Optional supplied x position for line/area/bar. Draws an independent review marker without selecting or interpolating a measurement. Invalid/out-of-window positions are omitted; null clears it."
87
+ },
88
+ cursorLabel: {
89
+ type: "string",
90
+ default: "Review position",
91
+ description: "Visible label for the supplied marker. Its value uses formatX and xUnit."
92
+ },
93
+ bins: {
94
+ type: "number",
95
+ default: 10,
96
+ description: "Histogram bin count, floored and clamped to 1\u2013100. Non-finite values use 10. Constant data uses one bin. Each histogram bins valid point.y values on a shared range; the last bin includes the maximum."
97
+ },
98
+ threshold: {
99
+ type: "node",
100
+ description: "Optional { value: number, label: string } on the measured y axis (count for histograms). Adds a dashed line and text. Non-finite values and heatmap thresholds are ignored."
101
+ }
102
+ },
103
+ composable_with: ["Card", "DataGrid", "TimeRange", "SplitPane"],
104
+ never_inside: ["Chart", "Button"],
105
+ example: '<Chart label="Link latency" unit="ms" xLabel="Elapsed" xUnit="s" series={[{ id: "alpha", label: "Alpha", data: [{ x: 0, y: 22 }, { x: 1, y: null }, { x: 2, y: 25 }] }]} />'
106
+ }
107
+ };
108
+ export {
109
+ ChartManifest
110
+ };
@@ -0,0 +1,190 @@
1
+ "use client";
2
+
3
+ // src/Chart/ChartControls.tsx
4
+ import { memo, useEffect, useMemo, useRef } from "react";
5
+ import { Slider, SliderFill, SliderThumb, SliderTrack } from "react-aria-components";
6
+ import clsx from "clsx";
7
+ import { Button } from "../Button/Button.js";
8
+ import { useHydrationRoot } from "../_internal/hydration.js";
9
+ import {
10
+ extent,
11
+ fraction,
12
+ interpolate,
13
+ isFinitePoint,
14
+ linePath,
15
+ scale,
16
+ segments,
17
+ seriesColorClass
18
+ } from "./geometry.js";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ function ChartInspection({
21
+ label,
22
+ index,
23
+ count,
24
+ describe,
25
+ onChange,
26
+ onFocus,
27
+ onBlur,
28
+ inputRef
29
+ }) {
30
+ const hydration = useHydrationRoot();
31
+ useEffect(() => {
32
+ inputRef.current?.setAttribute("aria-valuetext", describe(index));
33
+ });
34
+ return /* @__PURE__ */ jsx(
35
+ Slider,
36
+ {
37
+ ...hydration.probeProps,
38
+ "aria-label": `Inspect ${label}`,
39
+ minValue: 0,
40
+ maxValue: Math.max(1, count - 1),
41
+ value: index,
42
+ onChange: (value) => onChange(Math.min(count - 1, value)),
43
+ className: "absolute inset-0 pointer-events-none",
44
+ children: /* @__PURE__ */ jsx(SliderTrack, { className: "sr-only", children: /* @__PURE__ */ jsx(SliderThumb, { inputRef, onFocus, onBlur }) })
45
+ },
46
+ hydration.key
47
+ );
48
+ }
49
+ var ChartRangeSelector = memo(function ChartRangeSelector2({
50
+ label,
51
+ series,
52
+ domain,
53
+ range,
54
+ format,
55
+ renderPosition,
56
+ disabled,
57
+ onChange
58
+ }) {
59
+ const hydration = useHydrationRoot();
60
+ const startRef = useRef(null);
61
+ const endRef = useRef(null);
62
+ useEffect(() => {
63
+ startRef.current?.setAttribute("aria-valuetext", format(range.start));
64
+ endRef.current?.setAttribute("aria-valuetext", format(range.end));
65
+ });
66
+ const start = fraction(range.start, domain) * 1e3;
67
+ const end = fraction(range.end, domain) * 1e3;
68
+ const overview = useMemo(() => {
69
+ const overviewSeries = series.map((item) => ({
70
+ ...item,
71
+ data: item.data.filter(
72
+ (point) => !Number.isFinite(point.x) || point.x >= domain.min && point.x <= domain.max
73
+ )
74
+ }));
75
+ const overviewY = scale(
76
+ extent(
77
+ overviewSeries.flatMap((item) => item.data.filter(isFinitePoint).map((point) => point.y))
78
+ ),
79
+ 44,
80
+ 4
81
+ );
82
+ const overviewX = scale(domain, 0, 1e3);
83
+ return overviewSeries.map((item) => /* @__PURE__ */ jsx("g", { className: seriesColorClass(item.id, item.color), children: segments(item.data).map((run, index) => /* @__PURE__ */ jsx(
84
+ "path",
85
+ {
86
+ d: linePath(run, overviewX, overviewY),
87
+ fill: "none",
88
+ stroke: "currentColor",
89
+ strokeWidth: "var(--oprt-chart-stroke-width)",
90
+ vectorEffect: "non-scaling-stroke"
91
+ },
92
+ index
93
+ )) }, item.id));
94
+ }, [series, domain]);
95
+ const full = range.start === domain.min && range.end === domain.max;
96
+ return /* @__PURE__ */ jsxs("div", { className: "mt-3u border-t border-oprt-border pt-2u", "data-chart-range": "", children: [
97
+ /* @__PURE__ */ jsxs("div", { className: "mb-1u flex flex-wrap items-center justify-between gap-1u", children: [
98
+ /* @__PURE__ */ jsx("span", { className: "text-oprt-base font-semibold uppercase tracking-oprt-caps", children: "Observation window" }),
99
+ /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ size: "sm",
103
+ variant: "ghost",
104
+ disabled: disabled || full,
105
+ onClick: () => onChange({ start: domain.min, end: domain.max }),
106
+ children: "Reset range"
107
+ }
108
+ )
109
+ ] }),
110
+ /* @__PURE__ */ jsx(
111
+ Slider,
112
+ {
113
+ ...hydration.probeProps,
114
+ "aria-label": `${label} observation window`,
115
+ minValue: 0,
116
+ maxValue: 1e3,
117
+ step: 1,
118
+ value: [start, end],
119
+ isDisabled: disabled,
120
+ className: "px-1.5u data-[disabled]:opacity-50",
121
+ onChange: (values) => {
122
+ const lower = values[0];
123
+ const upper = values[1];
124
+ if (lower >= upper) return;
125
+ onChange({
126
+ start: interpolate(domain, lower / 1e3),
127
+ end: interpolate(domain, upper / 1e3)
128
+ });
129
+ },
130
+ children: /* @__PURE__ */ jsxs(SliderTrack, { className: "relative h-6u w-full touch-none border-y border-oprt-border bg-oprt-surface-2", children: [
131
+ /* @__PURE__ */ jsxs(
132
+ "svg",
133
+ {
134
+ "data-chart-overview": "",
135
+ "aria-hidden": "true",
136
+ viewBox: "0 0 1000 48",
137
+ preserveAspectRatio: "none",
138
+ className: "pointer-events-none absolute inset-0 h-full w-full",
139
+ children: [
140
+ overview,
141
+ /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: start, height: 48, fill: "var(--oprt-bg)", opacity: 0.75 }),
142
+ /* @__PURE__ */ jsx(
143
+ "rect",
144
+ {
145
+ x: end,
146
+ y: 0,
147
+ width: 1e3 - end,
148
+ height: 48,
149
+ fill: "var(--oprt-bg)",
150
+ opacity: 0.75
151
+ }
152
+ )
153
+ ]
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsx(SliderFill, { className: "pointer-events-none absolute h-full border-y border-oprt-accent" }),
157
+ ["start", "end"].map((edge, index) => /* @__PURE__ */ jsx(
158
+ SliderThumb,
159
+ {
160
+ index,
161
+ "aria-label": `${label} window ${edge}`,
162
+ inputRef: index === 0 ? startRef : endRef,
163
+ className: "group/range top-1/2 flex h-full min-h-3u w-3u cursor-ew-resize items-center justify-center outline-hidden data-[disabled]:cursor-not-allowed",
164
+ children: /* @__PURE__ */ jsx(
165
+ "span",
166
+ {
167
+ className: clsx(
168
+ "flex h-full w-1u items-center justify-center border border-oprt-accent bg-oprt-surface-1",
169
+ "group-data-[focus-visible]/range:shadow-oprt-focus group-data-[focus-visible]/range:border-oprt-border-focus"
170
+ ),
171
+ children: /* @__PURE__ */ jsx("span", { className: "h-2u border-l border-oprt-accent" })
172
+ }
173
+ )
174
+ },
175
+ edge
176
+ ))
177
+ ] })
178
+ },
179
+ hydration.key
180
+ ),
181
+ /* @__PURE__ */ jsxs("div", { className: "mt-1u flex flex-wrap justify-between gap-1u font-mono text-oprt-base text-oprt-text-dim oprt-wrap-anywhere", children: [
182
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: renderPosition(range.start) }),
183
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: renderPosition(range.end) })
184
+ ] })
185
+ ] });
186
+ });
187
+ export {
188
+ ChartInspection,
189
+ ChartRangeSelector
190
+ };
@@ -0,0 +1,217 @@
1
+ // src/Chart/geometry.ts
2
+ function isFinitePoint(point) {
3
+ return Number.isFinite(point.x) && point.y !== null && Number.isFinite(point.y);
4
+ }
5
+ function extent(values, includeZero = false) {
6
+ let min = includeZero ? 0 : Infinity;
7
+ let max = includeZero ? 0 : -Infinity;
8
+ for (const value of values) {
9
+ if (!Number.isFinite(value)) continue;
10
+ min = Math.min(min, value);
11
+ max = Math.max(max, value);
12
+ }
13
+ return min === Infinity ? { min: 0, max: 1 } : { min, max };
14
+ }
15
+ function fraction(value, domain) {
16
+ if (domain.min === domain.max) return 0.5;
17
+ const span = domain.max - domain.min;
18
+ const ratio = Number.isFinite(span) ? (value - domain.min) / span : (value / 2 - domain.min / 2) / (domain.max / 2 - domain.min / 2);
19
+ return Math.max(0, Math.min(1, ratio));
20
+ }
21
+ function interpolate(domain, fraction2) {
22
+ if (fraction2 === 0) return domain.min;
23
+ if (fraction2 === 1) return domain.max;
24
+ return domain.min * (1 - fraction2) + domain.max * fraction2;
25
+ }
26
+ function scale(domain, start, end) {
27
+ return (value) => start + fraction(value, domain) * (end - start);
28
+ }
29
+ function ticks(domain, count = 5) {
30
+ if (domain.min === domain.max) return [domain.min];
31
+ return Array.from({ length: count }, (_, index) => interpolate(domain, index / (count - 1)));
32
+ }
33
+ function niceAxis(domain, wholeNumbers = false) {
34
+ const fallback = () => ({ domain, ticks: ticks(domain) });
35
+ const span = domain.max - domain.min;
36
+ if (!Number.isFinite(span) || span <= 0) return fallback();
37
+ const rough = span / 4;
38
+ const magnitude = 10 ** Math.floor(Math.log10(rough));
39
+ if (!Number.isFinite(magnitude) || magnitude === 0) return fallback();
40
+ const ratio = rough / magnitude;
41
+ const step = Math.max(
42
+ wholeNumbers ? 1 : 0,
43
+ (ratio <= 1 ? 1 : ratio <= 2 ? 2 : ratio <= 5 ? 5 : 10) * magnitude
44
+ );
45
+ const min = Math.floor(domain.min / step) * step;
46
+ const max = Math.ceil(domain.max / step) * step;
47
+ const count = Math.round((max - min) / step);
48
+ if (![min, max, step, count].every(Number.isFinite) || step <= 0 || count < 1 || count > 10)
49
+ return fallback();
50
+ const values = Array.from(
51
+ { length: count + 1 },
52
+ (_, index) => Number((min + index * step).toPrecision(14))
53
+ );
54
+ if (values[0] > domain.min || values[values.length - 1] < domain.max) return fallback();
55
+ return { domain: { min: values[0], max: values[values.length - 1] }, ticks: values };
56
+ }
57
+ function segments(points) {
58
+ const result = [];
59
+ let segment = [];
60
+ for (const point of points) {
61
+ if (isFinitePoint(point)) segment.push(point);
62
+ else if (segment.length) {
63
+ result.push(segment);
64
+ segment = [];
65
+ }
66
+ }
67
+ if (segment.length) result.push(segment);
68
+ return result;
69
+ }
70
+ function markerPoints(runs, x) {
71
+ const marked = /* @__PURE__ */ new Set();
72
+ for (const run of runs) {
73
+ if (!run.length) continue;
74
+ const first = run[0];
75
+ const last = run[run.length - 1];
76
+ marked.add(first);
77
+ let previousX = x(first.x);
78
+ for (const point of run.slice(1, -1)) {
79
+ const position = x(point.x);
80
+ if (Math.abs(position - previousX) >= 48 && Math.abs(x(last.x) - position) >= 48) {
81
+ marked.add(point);
82
+ previousX = position;
83
+ }
84
+ }
85
+ marked.add(last);
86
+ }
87
+ return marked;
88
+ }
89
+ function indexByX(points) {
90
+ const index = /* @__PURE__ */ new Map();
91
+ for (const point of points) {
92
+ if (Number.isFinite(point.x) && !index.has(point.x)) index.set(point.x, point);
93
+ }
94
+ return index;
95
+ }
96
+ function nearestIndex(values, position, toPosition) {
97
+ if (values.length === 0) return -1;
98
+ let low = 0;
99
+ let high = values.length;
100
+ while (low < high) {
101
+ const middle = low + high >>> 1;
102
+ if (toPosition(values[middle]) < position) low = middle + 1;
103
+ else high = middle;
104
+ }
105
+ if (low === 0) return 0;
106
+ if (low === values.length) return values.length - 1;
107
+ const before = Math.abs(toPosition(values[low - 1]) - position);
108
+ const after = Math.abs(toPosition(values[low]) - position);
109
+ return after < before ? low : low - 1;
110
+ }
111
+ function linePath(points, x, y) {
112
+ return points.map((point, index) => `${index === 0 ? "M" : "L"}${x(point.x)},${y(point.y)}`).join(" ");
113
+ }
114
+ function seriesIdentity(id) {
115
+ let hash = 2166136261;
116
+ for (let i = 0; i < id.length; i++) hash = Math.imul(hash ^ id.charCodeAt(i), 16777619);
117
+ return (hash >>> 0) % 8;
118
+ }
119
+ var categoryClasses = [
120
+ "text-oprt-cat-1",
121
+ "text-oprt-cat-2",
122
+ "text-oprt-cat-3",
123
+ "text-oprt-cat-4",
124
+ "text-oprt-cat-5",
125
+ "text-oprt-cat-6",
126
+ "text-oprt-cat-7",
127
+ "text-oprt-cat-8"
128
+ ];
129
+ function seriesColorClass(id, color) {
130
+ if (color !== void 0 && Number.isInteger(color) && color >= 1 && color <= 8) {
131
+ return categoryClasses[color - 1];
132
+ }
133
+ return categoryClasses[id === void 0 ? 0 : seriesIdentity(id)];
134
+ }
135
+ var sequentialClasses = [
136
+ "text-oprt-data-seq-1",
137
+ "text-oprt-data-seq-2",
138
+ "text-oprt-data-seq-3",
139
+ "text-oprt-data-seq-4",
140
+ "text-oprt-data-seq-5"
141
+ ];
142
+ var exactAt = (value, decimals) => Math.abs(Number(value.toFixed(decimals)) - value) <= Math.abs(value) * 1e-12;
143
+ var withoutFloatNoise = (value) => Number.isFinite(value) ? Number(value.toPrecision(15)) : value;
144
+ var Y_LABEL_LIMIT = 11;
145
+ var MAX_FRACTION_DIGITS = 20;
146
+ function fittedScientific(value, locale, limit) {
147
+ const exactDigits = /\.(\d+)e/.exec(value.toExponential())?.[1]?.length ?? 0;
148
+ for (let digits = exactDigits; ; digits--) {
149
+ const text = new Intl.NumberFormat(locale, {
150
+ notation: "scientific",
151
+ maximumFractionDigits: digits
152
+ }).format(value);
153
+ if (text.length <= limit || digits === 0) return text;
154
+ }
155
+ }
156
+ function tickLabels(values, locale) {
157
+ const finite = values.filter(Number.isFinite).sort((a, b) => a - b);
158
+ let step = Infinity;
159
+ for (let index = 1; index < finite.length; index++) {
160
+ const gap = finite[index] - finite[index - 1];
161
+ if (gap > 0) step = Math.min(step, gap);
162
+ }
163
+ if (!Number.isFinite(step)) {
164
+ const exact = new Intl.NumberFormat(locale, { maximumSignificantDigits: 21 });
165
+ return values.map((value) => {
166
+ const text = exact.format(value + 0);
167
+ return text.length <= Y_LABEL_LIMIT ? text : fittedScientific(value, locale, Y_LABEL_LIMIT);
168
+ });
169
+ }
170
+ const stepExponent = Math.floor(Math.log10(step) + 1e-9);
171
+ let decimals = Math.max(0, -stepExponent);
172
+ while (decimals < 6 && !finite.every((value) => exactAt(value, decimals))) decimals++;
173
+ if (decimals <= MAX_FRACTION_DIGITS) {
174
+ const format = new Intl.NumberFormat(locale, {
175
+ minimumFractionDigits: decimals,
176
+ maximumFractionDigits: decimals
177
+ });
178
+ const labels = values.map((value) => format.format(value + 0));
179
+ if (labels.every((label) => label.length <= Y_LABEL_LIMIT)) return labels;
180
+ }
181
+ const largest = Math.max(...finite.map(Math.abs));
182
+ const largestExponent = largest === 0 ? stepExponent : Math.floor(Math.log10(largest) + 1e-9);
183
+ const digits = Math.min(16, Math.max(0, largestExponent - stepExponent));
184
+ const scientific = new Intl.NumberFormat(locale, {
185
+ notation: "scientific",
186
+ minimumFractionDigits: digits,
187
+ maximumFractionDigits: digits
188
+ });
189
+ const zero = new Intl.NumberFormat(locale).format(0);
190
+ return values.map((value) => value === 0 ? zero : scientific.format(value));
191
+ }
192
+ function intervalSeparator(locale) {
193
+ const decimal = new Intl.NumberFormat(locale).formatToParts(1.5).find((part) => part.type === "decimal");
194
+ return decimal?.value === "," ? "; " : ", ";
195
+ }
196
+ export {
197
+ Y_LABEL_LIMIT,
198
+ categoryClasses,
199
+ extent,
200
+ fraction,
201
+ indexByX,
202
+ interpolate,
203
+ intervalSeparator,
204
+ isFinitePoint,
205
+ linePath,
206
+ markerPoints,
207
+ nearestIndex,
208
+ niceAxis,
209
+ scale,
210
+ segments,
211
+ sequentialClasses,
212
+ seriesColorClass,
213
+ seriesIdentity,
214
+ tickLabels,
215
+ ticks,
216
+ withoutFloatNoise
217
+ };
@@ -0,0 +1,9 @@
1
+ // src/Chart/index.ts
2
+ import {
3
+ Chart
4
+ } from "./Chart.js";
5
+ import { ChartManifest } from "./Chart.manifest.js";
6
+ export {
7
+ Chart,
8
+ ChartManifest
9
+ };
@@ -0,0 +1,166 @@
1
+ "use client";
2
+
3
+ // src/Checkbox/Checkbox.tsx
4
+ import { Checkbox as AriaCheckbox } from "react-aria-components";
5
+ import { cva } from "class-variance-authority";
6
+ import { forwardRef, useRef, useState } from "react";
7
+ import clsx from "clsx";
8
+ import { useMotion } from "../_internal/motion.js";
9
+ import { Check, Minus } from "@oprt/icons";
10
+ import { useFieldWiring } from "../_internal/fieldIds.js";
11
+ import { CheckboxManifest } from "./Checkbox.manifest.js";
12
+ import { devValidate } from "../_internal/devValidate.js";
13
+ import { definedOnly, useAriaInvalidRef } from "../_internal/aria.js";
14
+ import { keyForIds } from "../_internal/hydration.js";
15
+ import { FORCED_CHECKBOX_BOX } from "../_internal/controlStyles.js";
16
+ import { useInputRefObject } from "../_internal/mergeRefs.js";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ var rootStyles = cva(
19
+ // Selected state = a checkmark on the surface (not a solid fill). The box border
20
+ // turns accent; the check (or, for tri-state, the bar) is the accent mark inside.
21
+ //
22
+ // RAC state attributes replace the Radix ones: data-selected / data-indeterminate
23
+ // instead of data-state, data-focus-visible instead of the :focus-visible
24
+ // pseudo-class (the role element is a hidden <input>, so the pseudo-class would
25
+ // never match the hidden input), data-disabled instead of :disabled. A named
26
+ // label group forwards those states to the visual box inside its 24px target.
27
+ // RAC has no
28
+ // "unselected" attribute, so the resting border is the base class and the selected
29
+ // variants override it (attribute selectors out-specify a plain class). The resting border is
30
+ // the control outline (design call DC-3); an invalid box takes the error color whether it is
31
+ // checked or not (the Toggle-R5 precedent): Tailwind sorts these state variants by name, so
32
+ // `selected` would win a tie, and `[&&]` raises the invalid rule above it.
33
+ "relative inline-flex items-center justify-center border bg-oprt-surface-2 oprt-motion-track group-data-[focus-visible]/checkbox:border-oprt-border-focus group-data-[focus-visible]/checkbox:shadow-oprt-focus group-data-[disabled]/checkbox:opacity-50 group-data-[disabled]/checkbox:cursor-not-allowed border-oprt-border-control group-data-[selected]/checkbox:border-oprt-accent group-data-[indeterminate]/checkbox:border-oprt-accent group-data-[invalid]/checkbox:[&&]:border-oprt-error",
34
+ {
35
+ variants: {
36
+ size: {
37
+ sm: "h-2u w-2u",
38
+ md: "h-2.5u w-2.5u",
39
+ lg: "h-3u w-3u"
40
+ }
41
+ },
42
+ defaultVariants: { size: "md" }
43
+ }
44
+ );
45
+ var Checkbox = forwardRef((props, ref) => {
46
+ const {
47
+ className,
48
+ motion = "auto",
49
+ size,
50
+ id,
51
+ checked,
52
+ defaultChecked,
53
+ onCheckedChange,
54
+ disabled,
55
+ required,
56
+ name,
57
+ value,
58
+ "aria-label": ariaLabel,
59
+ "aria-labelledby": ariaLabelledBy,
60
+ "aria-describedby": ariaDescribedBy,
61
+ "aria-invalid": ariaInvalid
62
+ } = props;
63
+ const motionState = useMotion(motion);
64
+ const {
65
+ id: finalId,
66
+ labelledBy,
67
+ describedBy,
68
+ invalid: isInvalid,
69
+ required: isRequired
70
+ } = useFieldWiring(
71
+ {
72
+ id,
73
+ "aria-label": ariaLabel,
74
+ "aria-labelledby": ariaLabelledBy,
75
+ "aria-describedby": ariaDescribedBy,
76
+ "aria-invalid": ariaInvalid,
77
+ required
78
+ },
79
+ { label: "labelledby" }
80
+ );
81
+ if (process.env.NODE_ENV !== "production") {
82
+ devValidate("Checkbox", CheckboxManifest.Checkbox.props, { ...props });
83
+ }
84
+ const isControlled = checked !== void 0;
85
+ const [uncontrolledIndeterminate, setUncontrolledIndeterminate] = useState(
86
+ defaultChecked === "indeterminate"
87
+ );
88
+ const isIndeterminate = isControlled ? checked === "indeterminate" : uncontrolledIndeterminate;
89
+ const setNode = useAriaInvalidRef(ref, isInvalid);
90
+ const inputRef = useInputRefObject(setNode);
91
+ const deferredInputMotion = useRef(null);
92
+ const motionProps = {
93
+ ...motionState.props,
94
+ onClickCapture: (event) => {
95
+ const nativeClick = event.nativeEvent;
96
+ const deferMotion = event.target === inputRef.current && event.detail === 0;
97
+ deferredInputMotion.current = deferMotion ? nativeClick : null;
98
+ if (deferMotion) {
99
+ setTimeout(() => {
100
+ if (deferredInputMotion.current === nativeClick) deferredInputMotion.current = null;
101
+ }, 0);
102
+ } else {
103
+ motionState.props.onClickCapture(event);
104
+ }
105
+ }
106
+ };
107
+ const rootProps = {
108
+ isDisabled: disabled ?? false,
109
+ isRequired,
110
+ isInvalid,
111
+ isIndeterminate,
112
+ onChange: (next) => {
113
+ const settleMotion = deferredInputMotion.current;
114
+ deferredInputMotion.current = null;
115
+ if (!isControlled) setUncontrolledIndeterminate(false);
116
+ onCheckedChange?.(next);
117
+ if (settleMotion) motionState.settleInput();
118
+ },
119
+ ...definedOnly({
120
+ id: finalId,
121
+ "aria-label": ariaLabel,
122
+ "aria-labelledby": labelledBy,
123
+ "aria-describedby": describedBy,
124
+ name,
125
+ value
126
+ })
127
+ };
128
+ if (isControlled) rootProps["isSelected"] = checked === true;
129
+ if (defaultChecked !== void 0) {
130
+ rootProps["defaultSelected"] = defaultChecked === true;
131
+ }
132
+ return /* @__PURE__ */ jsx(
133
+ AriaCheckbox,
134
+ {
135
+ ...rootProps,
136
+ ...motionProps,
137
+ render: (domProps) => /* @__PURE__ */ jsx("label", { ...domProps, ...motionProps }),
138
+ inputRef,
139
+ className: clsx(
140
+ "oprt-motion group/checkbox relative inline-flex self-start w-fit items-center justify-center min-h-3u min-w-3u cursor-pointer data-[disabled]:cursor-not-allowed",
141
+ className
142
+ ),
143
+ children: /* @__PURE__ */ jsxs("span", { className: clsx(rootStyles({ size }), "text-oprt-accent", FORCED_CHECKBOX_BOX), children: [
144
+ /* @__PURE__ */ jsx(
145
+ Check,
146
+ {
147
+ size: size === "sm" ? 12 : size === "lg" ? 20 : 16,
148
+ className: "oprt-cb-check oprt-motion-check shrink-0"
149
+ }
150
+ ),
151
+ /* @__PURE__ */ jsx(
152
+ Minus,
153
+ {
154
+ size: size === "sm" ? 12 : size === "lg" ? 20 : 16,
155
+ className: "oprt-cb-bar oprt-motion-check shrink-0"
156
+ }
157
+ )
158
+ ] })
159
+ },
160
+ keyForIds(finalId, labelledBy)
161
+ );
162
+ });
163
+ Checkbox.displayName = "Checkbox";
164
+ export {
165
+ Checkbox
166
+ };