@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,50 @@
1
+ // src/Popover/Popover.manifest.ts
2
+ var PopoverManifest = {
3
+ Popover: {
4
+ description: "Named nonmodal interactive details anchored to an explicitly activated trigger.",
5
+ props: {
6
+ title: {
7
+ type: "string",
8
+ description: "Visible heading that names the dialog; required unless aria-label is set."
9
+ },
10
+ "aria-label": {
11
+ type: "string",
12
+ description: "Name without a visible heading; required unless title is set."
13
+ },
14
+ open: { type: "boolean" },
15
+ defaultOpen: { type: "boolean", default: false },
16
+ onOpenChange: { type: "function" },
17
+ side: { type: "enum", values: ["top", "right", "bottom", "left"], default: "bottom" },
18
+ align: { type: "enum", values: ["start", "center", "end"], default: "start" },
19
+ disabled: { type: "boolean", default: false },
20
+ motion: { type: "enum", values: ["auto", "none"], default: "auto" },
21
+ description: {
22
+ type: "string",
23
+ description: "Short summary: a tooltip preview on the trigger and a line under the title of the open surface, which it describes. A disabled trigger with a description stays focusable, so focus or a tap shows it."
24
+ },
25
+ returnFocusRef: {
26
+ type: "node",
27
+ description: "RefObject<HTMLElement | null> fallback when the trigger is removed."
28
+ },
29
+ onCloseAutoFocus: { type: "function" },
30
+ className: { type: "string" }
31
+ },
32
+ slots: {
33
+ children: { type: "single focusable trigger element", required: true },
34
+ content: { type: "node", required: true }
35
+ },
36
+ composable_with: [
37
+ "Button",
38
+ "EntityPreview",
39
+ "DescriptionList",
40
+ "CopyButton",
41
+ "Inspector",
42
+ "Tooltip"
43
+ ],
44
+ never_inside: ["Tooltip"],
45
+ example: '<Popover title="Equipment details" description="Equipment operational" content={<button>Inspect</button>}><Button>Details</Button></Popover>'
46
+ }
47
+ };
48
+ export {
49
+ PopoverManifest
50
+ };
@@ -0,0 +1,7 @@
1
+ // src/Popover/index.ts
2
+ import { Popover } from "./Popover.js";
3
+ import { PopoverManifest } from "./Popover.manifest.js";
4
+ export {
5
+ Popover,
6
+ PopoverManifest
7
+ };
@@ -0,0 +1,132 @@
1
+ "use client";
2
+
3
+ // src/Progress/Progress.tsx
4
+ import { ProgressBar } from "react-aria-components";
5
+ import { cva } from "class-variance-authority";
6
+ import { forwardRef } from "react";
7
+ import clsx from "clsx";
8
+ import { ProgressManifest } from "./Progress.manifest.js";
9
+ import { devValidate } from "../_internal/devValidate.js";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ var rootStyles = cva(
12
+ "relative w-full overflow-hidden bg-oprt-surface-2 border border-oprt-border",
13
+ {
14
+ variants: {
15
+ size: {
16
+ sm: "h-1.5u",
17
+ md: "h-2u"
18
+ }
19
+ },
20
+ defaultVariants: { size: "md" }
21
+ }
22
+ );
23
+ var BLOCK_CELLS = 20;
24
+ var SOLID_FILL = "bg-oprt-accent forced-colors:bg-[CanvasText] forced-colors:[forced-color-adjust:none]";
25
+ var HATCH_FILL = "[--oprt-hatch:var(--oprt-accent)] forced-colors:[--oprt-hatch:CanvasText] forced-colors:[forced-color-adjust:none] [background-image:repeating-linear-gradient(135deg,var(--oprt-hatch)_0,var(--oprt-hatch)_var(--oprt-space-0-5),transparent_var(--oprt-space-0-5),transparent_var(--oprt-space-1))]";
26
+ var SLIDE_STILL = "motion-reduce:animate-none forced-colors:animate-none";
27
+ var BLOCK_HATCH = ["\u259A", "\u259E"];
28
+ var Progress = forwardRef((allProps, ref) => {
29
+ const {
30
+ className,
31
+ value,
32
+ max = 100,
33
+ label,
34
+ showValue = false,
35
+ variant,
36
+ size,
37
+ ...props
38
+ } = allProps;
39
+ const blocks = variant === "blocks";
40
+ const sizeKey = size === "sm" ? "sm" : "md";
41
+ const safeMax = Number.isFinite(max) && max > 0 ? max : 100;
42
+ const indeterminate = value == null || !Number.isFinite(value);
43
+ const safeValue = indeterminate ? 0 : Math.min(safeMax, Math.max(0, value));
44
+ const pct = safeValue / safeMax * 100;
45
+ const ariaLabel = props["aria-label"] ?? label ?? "Progress";
46
+ const barProps = { maxValue: safeMax, minValue: 0 };
47
+ if (indeterminate) barProps["isIndeterminate"] = true;
48
+ else barProps["value"] = safeValue;
49
+ const filled = Math.round(pct / 100 * BLOCK_CELLS);
50
+ const fillState = indeterminate ? "indeterminate" : "determinate";
51
+ if (process.env.NODE_ENV !== "production") {
52
+ devValidate("Progress", ProgressManifest.Progress.props, allProps);
53
+ }
54
+ return (
55
+ // The wrapper takes the width its container gives it, in a flex row as in a block: a bar has no
56
+ // width of its own, and without this it was 2 px wide beside other content.
57
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 flex-col gap-1u font-sans", children: [
58
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-x-2u", children: [
59
+ label ? /* @__PURE__ */ jsx("span", { className: "m-0 min-w-0 oprt-wrap-anywhere text-oprt-sm uppercase tracking-oprt-sm text-oprt-text-dim", children: label }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }),
60
+ showValue && /* @__PURE__ */ jsx("span", { className: "m-0 shrink-0 font-mono text-oprt-base text-oprt-text tabular-nums", children: indeterminate ? "\u2014" : `${Math.round(pct)}%` })
61
+ ] }),
62
+ /* @__PURE__ */ jsx(
63
+ ProgressBar,
64
+ {
65
+ ref,
66
+ "aria-label": ariaLabel,
67
+ className: blocks ? clsx("font-mono text-oprt-base", className) : clsx(rootStyles({ size: sizeKey }), className),
68
+ ...barProps,
69
+ ...props,
70
+ children: blocks ? indeterminate ? (
71
+ // An unknown amount is a hatch of alternating quarter blocks: neither the empty glyph
72
+ // of 0% nor the full one of 100%. The fill is as wide as the twenty cells and clips the
73
+ // row, which slides two cells (one repeat, a tenth of its width) at a time; two more
74
+ // cells wait just before its start and slide in, so each loop ends as the next begins.
75
+ /* @__PURE__ */ jsx(
76
+ "span",
77
+ {
78
+ "aria-hidden": "true",
79
+ "data-oprt-progress-fill": fillState,
80
+ className: "flex w-fit max-w-full overflow-hidden",
81
+ children: /* @__PURE__ */ jsxs(
82
+ "span",
83
+ {
84
+ className: clsx(
85
+ "relative flex tracking-oprt-md oprt-motion-slide-[10%]",
86
+ SLIDE_STILL
87
+ ),
88
+ children: [
89
+ Array.from({ length: BLOCK_CELLS }, (_, i) => /* @__PURE__ */ jsx("span", { className: "text-oprt-accent", children: BLOCK_HATCH[i % 2] }, i)),
90
+ /* @__PURE__ */ jsx("span", { "data-oprt-progress-tail": "", className: "absolute right-full top-0 flex", children: BLOCK_HATCH.map((glyph) => /* @__PURE__ */ jsx("span", { className: "text-oprt-accent", children: glyph }, glyph)) })
91
+ ]
92
+ }
93
+ )
94
+ }
95
+ )
96
+ ) : /* @__PURE__ */ jsx(
97
+ "span",
98
+ {
99
+ "aria-hidden": "true",
100
+ "data-oprt-progress-fill": fillState,
101
+ className: "flex tracking-oprt-md",
102
+ children: Array.from({ length: BLOCK_CELLS }, (_, i) => /* @__PURE__ */ jsx("span", { className: i < filled ? "text-oprt-accent" : "text-oprt-text-dim", children: i < filled ? "\u2588" : "\u2591" }, i))
103
+ }
104
+ ) : (
105
+ // RAC has no Indicator part; the fill is a plain element inside the progressbar. A known
106
+ // value slides the fill in from the left; an unknown one covers the track with the hatch,
107
+ // and one repeat more before its start, so the slide never uncovers the track.
108
+ /* @__PURE__ */ jsx(
109
+ "div",
110
+ {
111
+ "data-oprt-progress-fill": fillState,
112
+ className: clsx(
113
+ "h-full",
114
+ indeterminate ? clsx(
115
+ HATCH_FILL,
116
+ "-ml-[var(--oprt-slide-distance)] w-[calc(100%+var(--oprt-slide-distance))] oprt-motion-slide",
117
+ SLIDE_STILL
118
+ ) : clsx(SOLID_FILL, "w-full transition-transform duration-oprt-normal")
119
+ ),
120
+ ...indeterminate ? {} : { style: { transform: `translateX(-${100 - pct}%)` } }
121
+ }
122
+ )
123
+ )
124
+ }
125
+ )
126
+ ] })
127
+ );
128
+ });
129
+ Progress.displayName = "Progress";
130
+ export {
131
+ Progress
132
+ };
@@ -0,0 +1,30 @@
1
+ // src/Progress/Progress.manifest.ts
2
+ var ProgressManifest = {
3
+ Progress: {
4
+ description: "Determinate or indeterminate progress indicator rendered as a filled bar or a row of block glyphs. It fills the width its container gives it.",
5
+ props: {
6
+ value: {
7
+ type: "number",
8
+ description: "Current progress, clamped from 0 to max. Omit or pass a non-finite value for an indeterminate (amount unknown) state: a full-width hatched fill that slides gently and stays a still hatch with reduced motion and in forced colors, so it never looks like 0% or 100%."
9
+ },
10
+ max: {
11
+ type: "number",
12
+ default: 100,
13
+ description: "Finite positive upper bound. Zero, negative, and non-finite values fall back to 100."
14
+ },
15
+ label: {
16
+ type: "string",
17
+ description: "Optional short progress heading, displayed uppercase. Long identifiers wrap beside the value."
18
+ },
19
+ showValue: { type: "boolean", default: false },
20
+ variant: { type: "enum", values: ["bar", "blocks"], default: "bar" },
21
+ size: { type: "enum", values: ["sm", "md"], default: "md" }
22
+ },
23
+ composable_with: ["Card", "Field"],
24
+ never_inside: ["Progress"],
25
+ example: "<Progress value={72} showValue />"
26
+ }
27
+ };
28
+ export {
29
+ ProgressManifest
30
+ };
@@ -0,0 +1,7 @@
1
+ // src/Progress/index.ts
2
+ import { Progress } from "./Progress.js";
3
+ import { ProgressManifest } from "./Progress.manifest.js";
4
+ export {
5
+ Progress,
6
+ ProgressManifest
7
+ };
@@ -0,0 +1,306 @@
1
+ "use client";
2
+
3
+ // src/PropertyFilter/PropertyFilter.tsx
4
+ import {
5
+ forwardRef,
6
+ useEffect,
7
+ useId,
8
+ useImperativeHandle,
9
+ useRef,
10
+ useState
11
+ } from "react";
12
+ import { cva } from "class-variance-authority";
13
+ import clsx from "clsx";
14
+ import { Button } from "../Button/Button.js";
15
+ import { Field } from "../Field/Field.js";
16
+ import { Input } from "../Input/Input.js";
17
+ import { Select, SelectOption } from "../Select/Select.js";
18
+ import { TagGroup } from "../TagGroup/TagGroup.js";
19
+ import { joinIds, usePartIds } from "../_internal/fieldIds.js";
20
+ import { useRestoreFocusOnRemoval } from "../_internal/useRestoreFocusOnRemoval.js";
21
+ import {
22
+ getPropertyFilterTokenError
23
+ } from "./tokenError.js";
24
+ import {
25
+ getPropertyFilterTokenError as getPropertyFilterTokenError2
26
+ } from "./tokenError.js";
27
+ import { jsx, jsxs } from "react/jsx-runtime";
28
+ var filterStyles = cva(
29
+ "flex min-w-0 flex-col gap-2u font-sans normal-case text-oprt-base text-oprt-text"
30
+ );
31
+ var controlStyles = "min-w-[min(100%,calc(24*var(--oprt-space-1)))] max-w-full grow basis-[calc(24*var(--oprt-space-1))]";
32
+ var selectStyles = "w-full min-w-0 max-w-full";
33
+ function tokenLabel(token, fields) {
34
+ const field = fields.find((candidate) => candidate.key === token.field);
35
+ const operator = field?.operators.find((candidate) => candidate.key === token.operator);
36
+ const value = field?.options?.find((option) => option.value === token.value)?.label ?? token.value;
37
+ const label = `${field?.label ?? token.field} ${operator?.label ?? token.operator}${value === null ? "" : ` ${value}`}`;
38
+ const error = getPropertyFilterTokenError(token, fields);
39
+ return error ? `Invalid filter: ${label}. ${error}` : label;
40
+ }
41
+ var PropertyFilter = forwardRef(
42
+ ({
43
+ fields,
44
+ value,
45
+ onValueChange,
46
+ label = "Filters",
47
+ disabled = false,
48
+ className,
49
+ id,
50
+ onFocusCapture,
51
+ onBlurCapture,
52
+ "aria-labelledby": labelledBy,
53
+ ...props
54
+ }, ref) => {
55
+ const instanceId = useId();
56
+ const root = useRef(null);
57
+ useImperativeHandle(ref, () => root.current, []);
58
+ const ids = usePartIds(["error"], {
59
+ id,
60
+ readRendered: () => root.current?.getAttribute("data-oprt-ids")
61
+ });
62
+ const nextId = useRef(0);
63
+ const addRef = useRef(null);
64
+ const clearRef = useRef(null);
65
+ const composing = useRef(false);
66
+ const pendingAdd = useRef(null);
67
+ const [draft, setDraft] = useState({ field: "", operator: "", value: "" });
68
+ const [error, setError] = useState(null);
69
+ const field = fields.find((candidate) => candidate.key === draft.field);
70
+ const operator = field?.operators.find((candidate) => candidate.key === draft.operator);
71
+ const fault = (control) => error?.control === control ? { invalid: true, "aria-describedby": ids.error } : {};
72
+ const clearLeft = useRef(false);
73
+ const restore = useRestoreFocusOnRemoval(root, {
74
+ track: (element) => element === clearRef.current ? void 0 : null,
75
+ findTarget: () => !clearLeft.current && !disabled && value.tokens.length === 0 ? addRef.current : null
76
+ });
77
+ useEffect(() => {
78
+ const pending = pendingAdd.current;
79
+ if (pending && value.tokens.some(
80
+ (token) => token.id === pending.token.id && token.field === pending.token.field && token.operator === pending.token.operator && token.value === pending.token.value
81
+ )) {
82
+ pendingAdd.current = null;
83
+ setDraft((current) => current === pending.draft ? { ...current, value: "" } : current);
84
+ }
85
+ }, [value]);
86
+ function addFilter() {
87
+ if (disabled || fields.length === 0) return;
88
+ if (!field || !operator) {
89
+ setError({
90
+ message: "Choose a field and operator before adding a filter.",
91
+ control: field ? "operator" : "field"
92
+ });
93
+ return;
94
+ }
95
+ let id2;
96
+ do {
97
+ id2 = `filter-${instanceId}-${++nextId.current}`;
98
+ } while (value.tokens.some((token2) => token2.id === id2));
99
+ const token = {
100
+ id: id2,
101
+ field: field.key,
102
+ operator: operator.key,
103
+ value: operator.requiresValue ? draft.value : null
104
+ };
105
+ const tokenError = getPropertyFilterTokenError(token, fields);
106
+ if (tokenError || operator.requiresValue && field.options?.some((option) => option.value === draft.value && option.disabled)) {
107
+ setError({
108
+ message: tokenError ?? `Choose an available value for ${field.label}.`,
109
+ control: "value"
110
+ });
111
+ return;
112
+ }
113
+ setError(null);
114
+ pendingAdd.current = { token, draft };
115
+ onValueChange({ ...value, tokens: [...value.tokens, token] });
116
+ }
117
+ return /* @__PURE__ */ jsxs(
118
+ "div",
119
+ {
120
+ ...props,
121
+ ref: root,
122
+ role: "group",
123
+ id: id ?? (labelledBy ? ids.base : void 0),
124
+ "aria-label": label,
125
+ "aria-labelledby": labelledBy ? joinIds(ids.base, labelledBy) : void 0,
126
+ "data-oprt-ids": ids.base,
127
+ className: clsx(filterStyles(), className),
128
+ onFocusCapture: (event) => {
129
+ onFocusCapture?.(event);
130
+ if (event.target === clearRef.current) clearLeft.current = false;
131
+ restore.onFocusCapture(event);
132
+ },
133
+ onBlurCapture: (event) => {
134
+ onBlurCapture?.(event);
135
+ const clear = clearRef.current;
136
+ if (event.target === clear && clear && !clear.disabled)
137
+ clearLeft.current = true;
138
+ restore.onBlurCapture(event);
139
+ },
140
+ children: [
141
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-end gap-2u", children: [
142
+ /* @__PURE__ */ jsx(Field, { label: "Field", className: controlStyles, children: /* @__PURE__ */ jsx(
143
+ Select,
144
+ {
145
+ value: draft.field,
146
+ placeholder: "Choose field",
147
+ disabled: disabled || fields.length === 0,
148
+ className: selectStyles,
149
+ ...fault("field"),
150
+ onValueChange: (key) => {
151
+ if (disabled) return;
152
+ const next = fields.find((candidate) => candidate.key === key);
153
+ setDraft({ field: key, operator: next?.operators[0]?.key ?? "", value: "" });
154
+ setError(null);
155
+ },
156
+ children: fields.map((item) => /* @__PURE__ */ jsx(SelectOption, { value: item.key, children: item.label }, item.key))
157
+ }
158
+ ) }),
159
+ /* @__PURE__ */ jsx(Field, { label: "Operator", className: controlStyles, children: /* @__PURE__ */ jsx(
160
+ Select,
161
+ {
162
+ value: draft.operator,
163
+ placeholder: "Choose operator",
164
+ disabled: disabled || !field || !field.operators.length,
165
+ className: selectStyles,
166
+ ...fault("operator"),
167
+ onValueChange: (key) => {
168
+ if (disabled) return;
169
+ const next = field?.operators.find((candidate) => candidate.key === key);
170
+ setDraft((current) => ({
171
+ ...current,
172
+ operator: key,
173
+ value: operator?.requiresValue === next?.requiresValue ? current.value : ""
174
+ }));
175
+ setError(null);
176
+ },
177
+ children: (field?.operators ?? []).map((item) => /* @__PURE__ */ jsx(SelectOption, { value: item.key, children: item.label }, item.key))
178
+ }
179
+ ) }),
180
+ operator?.requiresValue && /* @__PURE__ */ jsx(Field, { label: "Value", className: controlStyles, children: field?.options ? /* @__PURE__ */ jsx(
181
+ Select,
182
+ {
183
+ value: draft.value,
184
+ placeholder: "Choose value",
185
+ disabled,
186
+ className: selectStyles,
187
+ ...fault("value"),
188
+ onValueChange: (next) => {
189
+ if (!disabled) {
190
+ setDraft((current) => ({ ...current, value: next }));
191
+ setError(null);
192
+ }
193
+ },
194
+ children: field.options.map((option) => /* @__PURE__ */ jsx(
195
+ SelectOption,
196
+ {
197
+ value: option.value,
198
+ disabled: !!option.disabled,
199
+ children: option.label
200
+ },
201
+ option.value
202
+ ))
203
+ }
204
+ ) : /* @__PURE__ */ jsx(
205
+ Input,
206
+ {
207
+ value: draft.value,
208
+ disabled,
209
+ className: "w-full min-w-0",
210
+ ...fault("value"),
211
+ onChange: (event) => {
212
+ if (!disabled) {
213
+ setDraft((current) => ({ ...current, value: event.target.value }));
214
+ setError(null);
215
+ }
216
+ },
217
+ onCompositionStart: () => {
218
+ composing.current = true;
219
+ },
220
+ onCompositionEnd: () => {
221
+ composing.current = false;
222
+ },
223
+ onKeyDown: (event) => {
224
+ if (event.key !== "Enter") return;
225
+ if (composing.current || event.nativeEvent.isComposing || event.keyCode === 229)
226
+ return;
227
+ event.preventDefault();
228
+ addFilter();
229
+ }
230
+ }
231
+ ) }),
232
+ /* @__PURE__ */ jsx(
233
+ Button,
234
+ {
235
+ ref: addRef,
236
+ disabled: disabled || fields.length === 0,
237
+ onClick: addFilter,
238
+ "aria-describedby": error ? ids.error : void 0,
239
+ children: "Add filter"
240
+ }
241
+ )
242
+ ] }),
243
+ error && /* @__PURE__ */ jsx(
244
+ "p",
245
+ {
246
+ id: ids.error,
247
+ role: "alert",
248
+ className: "m-0 oprt-wrap-anywhere text-oprt-base text-oprt-error",
249
+ children: error.message
250
+ }
251
+ ),
252
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-end gap-2u", children: [
253
+ /* @__PURE__ */ jsx(Field, { label: "Match", className: "min-w-0 max-w-full", children: /* @__PURE__ */ jsxs(
254
+ Select,
255
+ {
256
+ value: value.match,
257
+ disabled,
258
+ className: selectStyles,
259
+ onValueChange: (match) => {
260
+ if (!disabled && (match === "all" || match === "any"))
261
+ onValueChange({ ...value, match });
262
+ },
263
+ children: [
264
+ /* @__PURE__ */ jsx(SelectOption, { value: "all", children: "All filters" }),
265
+ /* @__PURE__ */ jsx(SelectOption, { value: "any", children: "Any filter" })
266
+ ]
267
+ }
268
+ ) }),
269
+ /* @__PURE__ */ jsx(
270
+ Button,
271
+ {
272
+ ref: clearRef,
273
+ variant: "ghost",
274
+ disabled: disabled || value.tokens.length === 0,
275
+ onClick: () => {
276
+ if (disabled || value.tokens.length === 0) return;
277
+ onValueChange({ ...value, tokens: [] });
278
+ },
279
+ children: "Clear filters"
280
+ }
281
+ )
282
+ ] }),
283
+ /* @__PURE__ */ jsx(
284
+ TagGroup,
285
+ {
286
+ label: `${label}: active filters`,
287
+ items: value.tokens.map((token) => ({ id: token.id, label: tokenLabel(token, fields) })),
288
+ disabled,
289
+ emptyMessage: "No active filters",
290
+ returnFocusRef: addRef,
291
+ onRemove: (id2) => {
292
+ if (!disabled)
293
+ onValueChange({ ...value, tokens: value.tokens.filter((token) => token.id !== id2) });
294
+ }
295
+ }
296
+ )
297
+ ]
298
+ }
299
+ );
300
+ }
301
+ );
302
+ PropertyFilter.displayName = "PropertyFilter";
303
+ export {
304
+ PropertyFilter,
305
+ getPropertyFilterTokenError2 as getPropertyFilterTokenError
306
+ };
@@ -0,0 +1,32 @@
1
+ // src/PropertyFilter/PropertyFilter.manifest.ts
2
+ var PropertyFilterManifest = {
3
+ PropertyFilter: {
4
+ description: "Controlled flat property-filter editor with text or enum values, all/any matching and removable, semantically validated clauses.",
5
+ props: {
6
+ fields: {
7
+ type: "array",
8
+ required: true,
9
+ description: "Readonly PropertyFilterField[] with key, label, operators and optional value/label/disabled options. Operators have key, label and requiresValue."
10
+ },
11
+ value: {
12
+ type: "node",
13
+ required: true,
14
+ description: "PropertyFilterValue: match all or any, and readonly tokens containing id, field, operator and string or null value."
15
+ },
16
+ onValueChange: {
17
+ type: "function",
18
+ required: true,
19
+ description: "Requests the complete next value. The parent accepts it through value; declined updates keep tokens and addition drafts."
20
+ },
21
+ label: { type: "string", default: "Filters" },
22
+ disabled: { type: "boolean", default: false },
23
+ className: { type: "string" }
24
+ },
25
+ composable_with: ["TagGroup", "DataGrid", "CollectionState"],
26
+ never_inside: ["Button"],
27
+ example: '<PropertyFilter fields={fields} value={filter} onValueChange={setFilter} label="Equipment filters" />'
28
+ }
29
+ };
30
+ export {
31
+ PropertyFilterManifest
32
+ };
@@ -0,0 +1,11 @@
1
+ // src/PropertyFilter/index.ts
2
+ import { PropertyFilter } from "./PropertyFilter.js";
3
+ import {
4
+ getPropertyFilterTokenError
5
+ } from "./tokenError.js";
6
+ import { PropertyFilterManifest } from "./PropertyFilter.manifest.js";
7
+ export {
8
+ PropertyFilter,
9
+ PropertyFilterManifest,
10
+ getPropertyFilterTokenError
11
+ };
@@ -0,0 +1,17 @@
1
+ // src/PropertyFilter/tokenError.ts
2
+ function getPropertyFilterTokenError(token, fields) {
3
+ const field = fields.find((candidate) => candidate.key === token.field);
4
+ if (!field) return `Unknown field: ${token.field}.`;
5
+ const operator = field.operators.find((candidate) => candidate.key === token.operator);
6
+ if (!operator) return `Unknown operator for ${field.label}: ${token.operator}.`;
7
+ if (!operator.requiresValue)
8
+ return token.value === null ? null : `${field.label} ${operator.label} does not accept a value.`;
9
+ if (typeof token.value !== "string" || token.value.trim().length === 0)
10
+ return `Enter a value for ${field.label}.`;
11
+ if (field.options && !field.options.some((option) => option.value === token.value))
12
+ return `Unknown value for ${field.label}: ${token.value}.`;
13
+ return null;
14
+ }
15
+ export {
16
+ getPropertyFilterTokenError
17
+ };