@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.
- package/LICENSE +21 -0
- package/README.md +105 -2
- package/dist/ActionStatus/ActionStatus.js +104 -0
- package/dist/ActionStatus/ActionStatus.manifest.js +64 -0
- package/dist/ActionStatus/index.js +7 -0
- package/dist/Alert/Alert.js +86 -0
- package/dist/Alert/Alert.manifest.js +36 -0
- package/dist/Alert/index.js +7 -0
- package/dist/AppShell/AppShell.js +103 -0
- package/dist/AppShell/AppShell.manifest.js +66 -0
- package/dist/AppShell/index.js +9 -0
- package/dist/AttachmentPreview/AttachmentPreview.js +145 -0
- package/dist/AttachmentPreview/AttachmentPreview.manifest.js +42 -0
- package/dist/AttachmentPreview/index.js +9 -0
- package/dist/Avatar/Avatar.js +87 -0
- package/dist/Avatar/Avatar.manifest.js +25 -0
- package/dist/Avatar/index.js +7 -0
- package/dist/Badge/Badge.js +124 -0
- package/dist/Badge/Badge.manifest.js +41 -0
- package/dist/Badge/index.js +7 -0
- package/dist/Breadcrumb/Breadcrumb.js +64 -0
- package/dist/Breadcrumb/Breadcrumb.manifest.js +28 -0
- package/dist/Breadcrumb/index.js +7 -0
- package/dist/BulkActionBar/BulkActionBar.js +145 -0
- package/dist/BulkActionBar/BulkActionBar.manifest.js +46 -0
- package/dist/BulkActionBar/index.js +9 -0
- package/dist/BulkActionBar/selection.js +44 -0
- package/dist/BulkResults/BulkResults.js +269 -0
- package/dist/BulkResults/BulkResults.manifest.js +45 -0
- package/dist/BulkResults/index.js +7 -0
- package/dist/Button/Button.js +170 -0
- package/dist/Button/Button.manifest.js +36 -0
- package/dist/Button/index.js +7 -0
- package/dist/ButtonGroup/ButtonGroup.js +60 -0
- package/dist/ButtonGroup/ButtonGroup.manifest.js +22 -0
- package/dist/ButtonGroup/index.js +7 -0
- package/dist/Calendar/Calendar.js +106 -0
- package/dist/Calendar/Calendar.manifest.js +32 -0
- package/dist/Calendar/index.js +7 -0
- package/dist/Card/Card.js +70 -0
- package/dist/Card/Card.manifest.js +57 -0
- package/dist/Card/index.js +16 -0
- package/dist/Chart/Chart.js +1200 -0
- package/dist/Chart/Chart.manifest.js +110 -0
- package/dist/Chart/ChartControls.js +190 -0
- package/dist/Chart/geometry.js +217 -0
- package/dist/Chart/index.js +9 -0
- package/dist/Checkbox/Checkbox.js +166 -0
- package/dist/Checkbox/Checkbox.manifest.js +38 -0
- package/dist/Checkbox/index.js +7 -0
- package/dist/Collapsible/Collapsible.js +177 -0
- package/dist/Collapsible/Collapsible.manifest.js +54 -0
- package/dist/Collapsible/index.js +12 -0
- package/dist/CollectionState/CollectionState.js +68 -0
- package/dist/CollectionState/CollectionState.manifest.js +44 -0
- package/dist/CollectionState/index.js +7 -0
- package/dist/ComboBox/ComboBox.js +221 -0
- package/dist/ComboBox/ComboBox.manifest.js +87 -0
- package/dist/ComboBox/index.js +7 -0
- package/dist/CommandPalette/CommandPalette.js +276 -0
- package/dist/CommandPalette/CommandPalette.manifest.js +24 -0
- package/dist/CommandPalette/index.js +7 -0
- package/dist/ConfirmDialog/ConfirmDialog.js +84 -0
- package/dist/ConfirmDialog/ConfirmDialog.manifest.js +32 -0
- package/dist/ConfirmDialog/index.js +7 -0
- package/dist/ContextMenu/ContextMenu.js +192 -0
- package/dist/ContextMenu/ContextMenu.manifest.js +41 -0
- package/dist/ContextMenu/index.js +7 -0
- package/dist/CoordinateInput/CoordinateInput.js +141 -0
- package/dist/CoordinateInput/CoordinateInput.manifest.js +36 -0
- package/dist/CoordinateInput/index.js +9 -0
- package/dist/CopyButton/CopyButton.js +129 -0
- package/dist/CopyButton/CopyButton.manifest.js +35 -0
- package/dist/CopyButton/index.js +7 -0
- package/dist/DataGrid/DataGrid.js +459 -0
- package/dist/DataGrid/DataGrid.manifest.js +135 -0
- package/dist/DataGrid/PageControls.js +41 -0
- package/dist/DataGrid/index.js +9 -0
- package/dist/DataTable/DataTable.js +375 -0
- package/dist/DataTable/DataTable.manifest.js +86 -0
- package/dist/DataTable/index.js +9 -0
- package/dist/DataTable/sort.js +45 -0
- package/dist/DataTable/useScrollsSideways.js +61 -0
- package/dist/DataTable/useTableWindow.js +185 -0
- package/dist/DatePicker/DatePicker.js +187 -0
- package/dist/DatePicker/DatePicker.manifest.js +40 -0
- package/dist/DatePicker/index.js +7 -0
- package/dist/DateRangePicker/DateRangePicker.js +156 -0
- package/dist/DateRangePicker/DateRangePicker.manifest.js +41 -0
- package/dist/DateRangePicker/index.js +7 -0
- package/dist/DateTimePicker/DateTimePicker.js +213 -0
- package/dist/DateTimePicker/DateTimePicker.manifest.js +44 -0
- package/dist/DateTimePicker/index.js +7 -0
- package/dist/DescriptionList/DescriptionList.js +93 -0
- package/dist/DescriptionList/DescriptionList.manifest.js +40 -0
- package/dist/DescriptionList/index.js +9 -0
- package/dist/Dialog/Dialog.js +214 -0
- package/dist/Dialog/Dialog.manifest.js +31 -0
- package/dist/Dialog/index.js +7 -0
- package/dist/Divider/Divider.js +64 -0
- package/dist/Divider/Divider.manifest.js +21 -0
- package/dist/Divider/index.js +7 -0
- package/dist/DropdownMenu/DropdownMenu.js +170 -0
- package/dist/DropdownMenu/DropdownMenu.manifest.js +82 -0
- package/dist/DropdownMenu/index.js +16 -0
- package/dist/EntityPreview/EntityPreview.js +82 -0
- package/dist/EntityPreview/EntityPreview.manifest.js +43 -0
- package/dist/EntityPreview/index.js +7 -0
- package/dist/EventTimeline/EventTimeline.js +249 -0
- package/dist/EventTimeline/EventTimeline.manifest.js +57 -0
- package/dist/EventTimeline/index.js +7 -0
- package/dist/Field/Field.js +81 -0
- package/dist/Field/Field.manifest.js +32 -0
- package/dist/Field/index.js +9 -0
- package/dist/FileUpload/FileUpload.js +215 -0
- package/dist/FileUpload/FileUpload.manifest.js +48 -0
- package/dist/FileUpload/index.js +7 -0
- package/dist/FilterBar/FilterBar.js +173 -0
- package/dist/FilterBar/FilterBar.manifest.js +49 -0
- package/dist/FilterBar/index.js +7 -0
- package/dist/FormErrorSummary/FormErrorSummary.js +70 -0
- package/dist/FormErrorSummary/FormErrorSummary.manifest.js +29 -0
- package/dist/FormErrorSummary/index.js +9 -0
- package/dist/FormSection/FormSection.js +51 -0
- package/dist/FormSection/FormSection.manifest.js +30 -0
- package/dist/FormSection/index.js +7 -0
- package/dist/InlineEdit/InlineEdit.js +261 -0
- package/dist/InlineEdit/InlineEdit.manifest.js +40 -0
- package/dist/InlineEdit/index.js +7 -0
- package/dist/Input/Input.js +126 -0
- package/dist/Input/Input.manifest.js +49 -0
- package/dist/Input/index.js +7 -0
- package/dist/Inspector/Inspector.js +63 -0
- package/dist/Inspector/Inspector.manifest.js +35 -0
- package/dist/Inspector/index.js +7 -0
- package/dist/JobStatus/JobStatus.js +118 -0
- package/dist/JobStatus/JobStatus.manifest.js +53 -0
- package/dist/JobStatus/index.js +7 -0
- package/dist/LayerControl/LayerControl.js +199 -0
- package/dist/LayerControl/LayerControl.manifest.js +34 -0
- package/dist/LayerControl/index.js +7 -0
- package/dist/Link/Link.js +83 -0
- package/dist/Link/Link.manifest.js +37 -0
- package/dist/Link/index.js +7 -0
- package/dist/MapControls/MapControls.js +122 -0
- package/dist/MapControls/MapControls.manifest.js +31 -0
- package/dist/MapControls/index.js +7 -0
- package/dist/MapLegend/MapLegend.js +89 -0
- package/dist/MapLegend/MapLegend.manifest.js +29 -0
- package/dist/MapLegend/index.js +7 -0
- package/dist/MapScale/MapScale.js +96 -0
- package/dist/MapScale/MapScale.manifest.js +31 -0
- package/dist/MapScale/index.js +7 -0
- package/dist/MediaFrame/MediaFrame.js +113 -0
- package/dist/MediaFrame/MediaFrame.manifest.js +57 -0
- package/dist/MediaFrame/index.js +7 -0
- package/dist/MultiSelect/MultiSelect.js +113 -0
- package/dist/MultiSelect/MultiSelect.manifest.js +51 -0
- package/dist/MultiSelect/index.js +7 -0
- package/dist/NumberInput/NumberInput.js +210 -0
- package/dist/NumberInput/NumberInput.manifest.js +56 -0
- package/dist/NumberInput/index.js +7 -0
- package/dist/OperationalStatus/OperationalStatus.js +89 -0
- package/dist/OperationalStatus/OperationalStatus.manifest.js +39 -0
- package/dist/OperationalStatus/index.js +9 -0
- package/dist/PlaybackControls/PlaybackControls.js +289 -0
- package/dist/PlaybackControls/PlaybackControls.manifest.js +85 -0
- package/dist/PlaybackControls/index.js +7 -0
- package/dist/Popover/Popover.js +302 -0
- package/dist/Popover/Popover.manifest.js +50 -0
- package/dist/Popover/index.js +7 -0
- package/dist/Progress/Progress.js +132 -0
- package/dist/Progress/Progress.manifest.js +30 -0
- package/dist/Progress/index.js +7 -0
- package/dist/PropertyFilter/PropertyFilter.js +306 -0
- package/dist/PropertyFilter/PropertyFilter.manifest.js +32 -0
- package/dist/PropertyFilter/index.js +11 -0
- package/dist/PropertyFilter/tokenError.js +17 -0
- package/dist/RadioGroup/RadioGroup.js +143 -0
- package/dist/RadioGroup/RadioGroup.manifest.js +44 -0
- package/dist/RadioGroup/index.js +9 -0
- package/dist/Select/Select.js +219 -0
- package/dist/Select/Select.manifest.js +77 -0
- package/dist/Select/index.js +9 -0
- package/dist/Sidebar/Sidebar.js +146 -0
- package/dist/Sidebar/Sidebar.manifest.js +72 -0
- package/dist/Sidebar/index.js +18 -0
- package/dist/Skeleton/Skeleton.js +76 -0
- package/dist/Skeleton/Skeleton.manifest.js +30 -0
- package/dist/Skeleton/index.js +7 -0
- package/dist/Slider/Slider.js +246 -0
- package/dist/Slider/Slider.manifest.js +56 -0
- package/dist/Slider/index.js +7 -0
- package/dist/Sparkline/Sparkline.js +135 -0
- package/dist/Sparkline/Sparkline.manifest.js +37 -0
- package/dist/Sparkline/index.js +7 -0
- package/dist/SplitPane/SplitPane.js +316 -0
- package/dist/SplitPane/SplitPane.manifest.js +79 -0
- package/dist/SplitPane/index.js +7 -0
- package/dist/StatCard/StatCard.js +163 -0
- package/dist/StatCard/StatCard.manifest.js +45 -0
- package/dist/StatCard/index.js +7 -0
- package/dist/Tabs/Tabs.js +181 -0
- package/dist/Tabs/Tabs.manifest.js +72 -0
- package/dist/Tabs/index.js +16 -0
- package/dist/Tabs/useTabsIndicator.js +71 -0
- package/dist/Tabs/useTabsScroll.js +123 -0
- package/dist/TagGroup/TagGroup.js +142 -0
- package/dist/TagGroup/TagGroup.manifest.js +35 -0
- package/dist/TagGroup/index.js +7 -0
- package/dist/Textarea/Textarea.js +68 -0
- package/dist/Textarea/Textarea.manifest.js +25 -0
- package/dist/Textarea/index.js +7 -0
- package/dist/TimeField/TimeField.js +118 -0
- package/dist/TimeField/TimeField.manifest.js +42 -0
- package/dist/TimeField/index.js +7 -0
- package/dist/TimeRange/TimeRange.js +184 -0
- package/dist/TimeRange/TimeRange.manifest.js +48 -0
- package/dist/TimeRange/index.js +9 -0
- package/dist/Toast/Toast.js +188 -0
- package/dist/Toast/Toast.manifest.js +77 -0
- package/dist/Toast/index.js +9 -0
- package/dist/Toggle/Toggle.js +154 -0
- package/dist/Toggle/Toggle.manifest.js +54 -0
- package/dist/Toggle/index.js +7 -0
- package/dist/Toolbar/Toolbar.js +86 -0
- package/dist/Toolbar/Toolbar.manifest.js +70 -0
- package/dist/Toolbar/index.js +12 -0
- package/dist/Tooltip/Tooltip.js +123 -0
- package/dist/Tooltip/Tooltip.manifest.js +27 -0
- package/dist/Tooltip/index.js +7 -0
- package/dist/TreeView/TreeView.js +129 -0
- package/dist/TreeView/TreeView.manifest.js +56 -0
- package/dist/TreeView/index.js +7 -0
- package/dist/UploadQueue/UploadQueue.js +296 -0
- package/dist/UploadQueue/UploadQueue.manifest.js +34 -0
- package/dist/UploadQueue/index.js +7 -0
- package/dist/_internal/MotionPopover.js +113 -0
- package/dist/_internal/aria.js +40 -0
- package/dist/_internal/bytes.js +18 -0
- package/dist/_internal/controlStyles.js +26 -0
- package/dist/_internal/date.js +179 -0
- package/dist/_internal/devValidate.js +51 -0
- package/dist/_internal/fieldIds.js +50 -0
- package/dist/_internal/hydration.js +74 -0
- package/dist/_internal/manifest-entry.js +0 -0
- package/dist/_internal/mergeRefs.js +68 -0
- package/dist/_internal/motion.js +138 -0
- package/dist/_internal/navigationLandmark.js +13 -0
- package/dist/_internal/numberText.js +176 -0
- package/dist/_internal/overlay.js +53 -0
- package/dist/_internal/segmentField.js +125 -0
- package/dist/_internal/suggestions.js +20 -0
- package/dist/_internal/timestamp.js +25 -0
- package/dist/_internal/unavailable.js +13 -0
- package/dist/_internal/useActionFocus.js +27 -0
- package/dist/_internal/useElementWidth.js +37 -0
- package/dist/_internal/useIsMounted.js +18 -0
- package/dist/_internal/useIsomorphicLayoutEffect.js +8 -0
- package/dist/_internal/useRestoreFocusOnRemoval.js +57 -0
- package/dist/index.cjs +17831 -0
- package/dist/index.d.cts +2330 -0
- package/dist/index.d.ts +2330 -0
- package/dist/index.js +407 -0
- package/dist/version.js +8 -0
- package/package.json +80 -3
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/EventTimeline/EventTimeline.tsx
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import {
|
|
7
|
+
forwardRef,
|
|
8
|
+
memo,
|
|
9
|
+
useCallback,
|
|
10
|
+
useId,
|
|
11
|
+
useMemo,
|
|
12
|
+
useRef,
|
|
13
|
+
useState
|
|
14
|
+
} from "react";
|
|
15
|
+
import { Badge } from "../Badge/Badge.js";
|
|
16
|
+
import { Button } from "../Button/Button.js";
|
|
17
|
+
import { useMergedRefs } from "../_internal/mergeRefs.js";
|
|
18
|
+
import { formatUtcTimestamp, isValidTimestamp } from "../_internal/timestamp.js";
|
|
19
|
+
import { useElementWidth } from "../_internal/useElementWidth.js";
|
|
20
|
+
import { useIsomorphicLayoutEffect } from "../_internal/useIsomorphicLayoutEffect.js";
|
|
21
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
var timelineStyles = cva("flex min-w-0 flex-col gap-2u font-sans text-oprt-text");
|
|
23
|
+
var markStyles = cva("fill-current", {
|
|
24
|
+
variants: {
|
|
25
|
+
severity: {
|
|
26
|
+
neutral: "text-oprt-text-dim",
|
|
27
|
+
info: "text-oprt-info",
|
|
28
|
+
success: "text-oprt-success",
|
|
29
|
+
warning: "text-oprt-warning",
|
|
30
|
+
error: "text-oprt-error"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: { severity: "neutral" }
|
|
34
|
+
});
|
|
35
|
+
var utc = (value) => formatUtcTimestamp(value, { precision: "milliseconds" }) ?? "";
|
|
36
|
+
var eventValid = (event) => isValidTimestamp(event.start) && (event.end === void 0 || isValidTimestamp(event.end) && event.end >= event.start);
|
|
37
|
+
var laneOf = (event) => event.lane || "Events";
|
|
38
|
+
var DEFAULT_WIDTH = 1e3;
|
|
39
|
+
var MIN_WIDTH = 16;
|
|
40
|
+
var Marker = memo(function Marker2({ id, severity, x, width, selected }) {
|
|
41
|
+
const classes = clsx(
|
|
42
|
+
markStyles({ severity: severity ?? "neutral" }),
|
|
43
|
+
selected && "stroke-oprt-text"
|
|
44
|
+
);
|
|
45
|
+
return width !== null ? /* @__PURE__ */ jsx(
|
|
46
|
+
"rect",
|
|
47
|
+
{
|
|
48
|
+
"data-event-id": id,
|
|
49
|
+
x,
|
|
50
|
+
y: selected ? 10 : 14,
|
|
51
|
+
width,
|
|
52
|
+
height: selected ? 28 : 20,
|
|
53
|
+
className: classes,
|
|
54
|
+
vectorEffect: "non-scaling-stroke"
|
|
55
|
+
}
|
|
56
|
+
) : /* @__PURE__ */ jsx(
|
|
57
|
+
"path",
|
|
58
|
+
{
|
|
59
|
+
"data-event-id": id,
|
|
60
|
+
d: `M ${x} 8 L ${x + 5} 24 L ${x} 40 L ${x - 5} 24 Z`,
|
|
61
|
+
className: classes,
|
|
62
|
+
vectorEffect: "non-scaling-stroke"
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
var TimelineRow = memo(function TimelineRow2({
|
|
67
|
+
event,
|
|
68
|
+
selected,
|
|
69
|
+
selectable,
|
|
70
|
+
disabled,
|
|
71
|
+
detailsId,
|
|
72
|
+
onSelect
|
|
73
|
+
}) {
|
|
74
|
+
return /* @__PURE__ */ jsxs(
|
|
75
|
+
"li",
|
|
76
|
+
{
|
|
77
|
+
className: clsx(
|
|
78
|
+
"flex min-w-0 flex-col gap-1u border p-2u",
|
|
79
|
+
selected ? "border-oprt-accent bg-oprt-surface-2" : "border-oprt-border"
|
|
80
|
+
),
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start gap-2u", children: [
|
|
83
|
+
selectable ? /* @__PURE__ */ jsx(
|
|
84
|
+
Button,
|
|
85
|
+
{
|
|
86
|
+
size: "sm",
|
|
87
|
+
variant: "ghost",
|
|
88
|
+
disabled,
|
|
89
|
+
className: "h-auto! min-h-3u min-w-0 flex-1 justify-start! px-0! whitespace-normal text-left normal-case! tracking-normal hover:underline",
|
|
90
|
+
"aria-pressed": selected,
|
|
91
|
+
"aria-describedby": detailsId,
|
|
92
|
+
onClick: () => {
|
|
93
|
+
if (!disabled) onSelect(event.id);
|
|
94
|
+
},
|
|
95
|
+
children: /* @__PURE__ */ jsx("span", { className: "block min-w-0 oprt-wrap-anywhere", children: event.label })
|
|
96
|
+
}
|
|
97
|
+
) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-oprt-base font-medium normal-case oprt-wrap-anywhere", children: event.label }),
|
|
98
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1u", children: [
|
|
99
|
+
/* @__PURE__ */ jsx(Badge, { variant: event.severity ?? "neutral", indicator: "dot", children: event.severity ?? "neutral" }),
|
|
100
|
+
selected && /* @__PURE__ */ jsx("span", { className: "text-oprt-base font-medium uppercase tracking-oprt-caps", children: "Selected" })
|
|
101
|
+
] })
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsxs("div", { id: detailsId, className: "flex min-w-0 flex-col gap-1u text-oprt-base normal-case", children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2u gap-y-1u text-oprt-text-dim", children: [
|
|
105
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 font-mono oprt-wrap-anywhere", children: [
|
|
106
|
+
/* @__PURE__ */ jsx("time", { dateTime: new Date(event.start).toISOString(), children: utc(event.start) }),
|
|
107
|
+
event.end !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
108
|
+
" \u2013 ",
|
|
109
|
+
/* @__PURE__ */ jsx("time", { dateTime: new Date(event.end).toISOString(), children: utc(event.end) })
|
|
110
|
+
] })
|
|
111
|
+
] }),
|
|
112
|
+
event.lane && /* @__PURE__ */ jsx("span", { className: "min-w-0 oprt-wrap-anywhere", children: event.lane })
|
|
113
|
+
] }),
|
|
114
|
+
event.description && /* @__PURE__ */ jsx("p", { className: "m-0 oprt-wrap-anywhere", children: event.description })
|
|
115
|
+
] })
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
var EventTimeline = forwardRef(
|
|
121
|
+
({
|
|
122
|
+
events,
|
|
123
|
+
start,
|
|
124
|
+
end,
|
|
125
|
+
selectedId,
|
|
126
|
+
onSelectionChange,
|
|
127
|
+
disabled = false,
|
|
128
|
+
label = "Event timeline",
|
|
129
|
+
emptyMessage = "No events in this time range.",
|
|
130
|
+
className,
|
|
131
|
+
...props
|
|
132
|
+
}, forwardedRef) => {
|
|
133
|
+
const id = useId();
|
|
134
|
+
const rootRef = useRef(null);
|
|
135
|
+
const setRef = useMergedRefs(rootRef, forwardedRef);
|
|
136
|
+
const observed = useElementWidth(rootRef, {
|
|
137
|
+
initial: null,
|
|
138
|
+
min: MIN_WIDTH
|
|
139
|
+
});
|
|
140
|
+
const [firstWidth, setFirstWidth] = useState(null);
|
|
141
|
+
useIsomorphicLayoutEffect(() => {
|
|
142
|
+
const width = rootRef.current?.getBoundingClientRect().width;
|
|
143
|
+
if (width !== void 0 && Number.isFinite(width) && width > MIN_WIDTH) setFirstWidth(width);
|
|
144
|
+
}, []);
|
|
145
|
+
const plotWidth = observed ?? firstWidth ?? DEFAULT_WIDTH;
|
|
146
|
+
const validRange = isValidTimestamp(start) && isValidTimestamp(end) && start < end;
|
|
147
|
+
const { visible, omitted, lanes } = useMemo(() => {
|
|
148
|
+
const validEvents = events.filter(eventValid);
|
|
149
|
+
const inWindow = validRange ? validEvents.filter((event) => event.start <= end && (event.end ?? event.start) >= start).sort((a, b) => a.start - b.start) : [];
|
|
150
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
151
|
+
for (const event of inWindow) {
|
|
152
|
+
const lane = laneOf(event);
|
|
153
|
+
const list = byLane.get(lane);
|
|
154
|
+
if (list) list.push(event);
|
|
155
|
+
else byLane.set(lane, [event]);
|
|
156
|
+
}
|
|
157
|
+
return { visible: inWindow, omitted: events.length - validEvents.length, lanes: byLane };
|
|
158
|
+
}, [events, start, end, validRange]);
|
|
159
|
+
const selectionRef = useRef(onSelectionChange);
|
|
160
|
+
useIsomorphicLayoutEffect(() => {
|
|
161
|
+
selectionRef.current = onSelectionChange;
|
|
162
|
+
});
|
|
163
|
+
const select = useCallback((eventId) => selectionRef.current?.(eventId), []);
|
|
164
|
+
const extent = plotWidth - 16;
|
|
165
|
+
const position = (time) => 8 + Math.max(0, Math.min(extent, (time - start) / (end - start) * extent));
|
|
166
|
+
return /* @__PURE__ */ jsxs(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
...props,
|
|
170
|
+
ref: setRef,
|
|
171
|
+
role: "group",
|
|
172
|
+
"aria-label": label,
|
|
173
|
+
className: clsx(timelineStyles(), className),
|
|
174
|
+
children: [
|
|
175
|
+
!validRange ? /* @__PURE__ */ jsx("p", { role: "status", className: "m-0 text-oprt-base text-oprt-text-dim", children: "Choose a valid time range with start before end." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
176
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-between gap-1u font-mono text-oprt-base text-oprt-text-dim", children: [
|
|
177
|
+
/* @__PURE__ */ jsx("time", { dateTime: new Date(start).toISOString(), children: utc(start) }),
|
|
178
|
+
/* @__PURE__ */ jsx("time", { dateTime: new Date(end).toISOString(), children: utc(end) })
|
|
179
|
+
] }),
|
|
180
|
+
visible.length === 0 ? /* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-base text-oprt-text-dim", children: emptyMessage }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
181
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "flex flex-col gap-1u", children: [...lanes].map(([lane, laneEvents]) => /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
182
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-oprt-base font-medium uppercase tracking-oprt-caps oprt-wrap-anywhere", children: lane }),
|
|
183
|
+
/* @__PURE__ */ jsxs(
|
|
184
|
+
"svg",
|
|
185
|
+
{
|
|
186
|
+
viewBox: `0 0 ${plotWidth} 48`,
|
|
187
|
+
preserveAspectRatio: "none",
|
|
188
|
+
className: "block h-6u w-full overflow-hidden",
|
|
189
|
+
focusable: "false",
|
|
190
|
+
children: [
|
|
191
|
+
/* @__PURE__ */ jsx(
|
|
192
|
+
"line",
|
|
193
|
+
{
|
|
194
|
+
x1: "8",
|
|
195
|
+
x2: plotWidth - 8,
|
|
196
|
+
y1: "24",
|
|
197
|
+
y2: "24",
|
|
198
|
+
className: "stroke-oprt-border",
|
|
199
|
+
vectorEffect: "non-scaling-stroke"
|
|
200
|
+
}
|
|
201
|
+
),
|
|
202
|
+
laneEvents.map((event) => {
|
|
203
|
+
const x = position(event.start);
|
|
204
|
+
const duration = event.end !== void 0 && event.end > event.start;
|
|
205
|
+
return /* @__PURE__ */ jsx(
|
|
206
|
+
Marker,
|
|
207
|
+
{
|
|
208
|
+
id: event.id,
|
|
209
|
+
severity: event.severity,
|
|
210
|
+
x,
|
|
211
|
+
width: duration ? Math.max(2, position(event.end) - x) : null,
|
|
212
|
+
selected: selectedId === event.id
|
|
213
|
+
},
|
|
214
|
+
event.id
|
|
215
|
+
);
|
|
216
|
+
})
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
] }, lane)) }),
|
|
221
|
+
/* @__PURE__ */ jsx("ol", { "aria-label": `${label} list`, className: "m-0 flex list-none flex-col gap-1u p-0", children: visible.map((event, index) => /* @__PURE__ */ jsx(
|
|
222
|
+
TimelineRow,
|
|
223
|
+
{
|
|
224
|
+
event,
|
|
225
|
+
selected: selectedId === event.id,
|
|
226
|
+
selectable: !!onSelectionChange,
|
|
227
|
+
disabled,
|
|
228
|
+
detailsId: `${id}-details-${index}`,
|
|
229
|
+
onSelect: select
|
|
230
|
+
},
|
|
231
|
+
event.id
|
|
232
|
+
)) })
|
|
233
|
+
] })
|
|
234
|
+
] }),
|
|
235
|
+
omitted > 0 && /* @__PURE__ */ jsxs("p", { className: "m-0 text-oprt-base text-oprt-text-dim", children: [
|
|
236
|
+
omitted,
|
|
237
|
+
" ",
|
|
238
|
+
omitted === 1 ? "event omitted" : "events omitted",
|
|
239
|
+
" because timestamps are invalid."
|
|
240
|
+
] })
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
EventTimeline.displayName = "EventTimeline";
|
|
247
|
+
export {
|
|
248
|
+
EventTimeline
|
|
249
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// src/EventTimeline/EventTimeline.manifest.ts
|
|
2
|
+
var EventTimelineManifest = {
|
|
3
|
+
EventTimeline: {
|
|
4
|
+
description: "UTC event graphic with lanes, clipped duration bars, point markers, and a complete accessible event list. Event titles lead each entry, severity aligns at the trailing edge, and timestamps/categories form a secondary metadata row.",
|
|
5
|
+
props: {
|
|
6
|
+
events: {
|
|
7
|
+
type: "array",
|
|
8
|
+
required: true,
|
|
9
|
+
description: "Readonly TimelineEvent array. Invalid timestamps and reversed intervals are omitted with an explicit count. The visible list is sorted by start time.",
|
|
10
|
+
items: {
|
|
11
|
+
id: "string (required, unique)",
|
|
12
|
+
label: "string (required)",
|
|
13
|
+
start: "number (required, epoch milliseconds)",
|
|
14
|
+
end: "number (optional, epoch milliseconds, inclusive)",
|
|
15
|
+
lane: "string (optional, defaults to Events)",
|
|
16
|
+
description: "string (optional)",
|
|
17
|
+
severity: "enum [neutral, info, success, warning, error] (default neutral)"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
start: {
|
|
21
|
+
type: "number",
|
|
22
|
+
required: true,
|
|
23
|
+
description: "Inclusive visible window start, Unix epoch milliseconds."
|
|
24
|
+
},
|
|
25
|
+
end: {
|
|
26
|
+
type: "number",
|
|
27
|
+
required: true,
|
|
28
|
+
description: "Inclusive visible window end, Unix epoch milliseconds. Must follow start."
|
|
29
|
+
},
|
|
30
|
+
selectedId: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Controlled selected event ID, or null for no selection. Filtering the visible window never changes the supplied selection."
|
|
33
|
+
},
|
|
34
|
+
onSelectionChange: {
|
|
35
|
+
type: "function",
|
|
36
|
+
description: "(id: string) => void. Adds native selection buttons to the event list; Enter and Space select an event."
|
|
37
|
+
},
|
|
38
|
+
disabled: {
|
|
39
|
+
type: "boolean",
|
|
40
|
+
default: false,
|
|
41
|
+
description: "Disables selection buttons while keeping data readable."
|
|
42
|
+
},
|
|
43
|
+
label: {
|
|
44
|
+
type: "string",
|
|
45
|
+
default: "Event timeline",
|
|
46
|
+
description: 'Accessible name of the group. The event list is named after it with "list" added (label="Service events" names the list "Service events list").'
|
|
47
|
+
},
|
|
48
|
+
emptyMessage: { type: "string", default: "No events in this time range." }
|
|
49
|
+
},
|
|
50
|
+
composable_with: ["TimeRange", "SplitPane", "Card"],
|
|
51
|
+
never_inside: ["Button"],
|
|
52
|
+
example: '<EventTimeline events={events} start={range.start} end={range.end} selectedId={selectedId} onSelectionChange={setSelectedId} label="Service events" />'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
EventTimelineManifest
|
|
57
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/Field/Field.tsx
|
|
4
|
+
import { forwardRef, useContext, useRef } from "react";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import { FieldContext, usePartIds } from "../_internal/fieldIds.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
function useFieldContext() {
|
|
9
|
+
const ctx = useContext(FieldContext);
|
|
10
|
+
if (!ctx) {
|
|
11
|
+
throw new Error("useFieldContext must be used inside a <Field>.");
|
|
12
|
+
}
|
|
13
|
+
return ctx;
|
|
14
|
+
}
|
|
15
|
+
function useOptionalFieldContext() {
|
|
16
|
+
return useContext(FieldContext);
|
|
17
|
+
}
|
|
18
|
+
var Field = forwardRef(
|
|
19
|
+
({ controlId, label, help, error, required, children, className, ...props }, ref) => {
|
|
20
|
+
const labelRef = useRef(null);
|
|
21
|
+
const ids = usePartIds(["label", "help", "error"], {
|
|
22
|
+
id: controlId,
|
|
23
|
+
readRendered: () => labelRef.current?.htmlFor
|
|
24
|
+
});
|
|
25
|
+
const id = ids.base;
|
|
26
|
+
const describedBy = error ? ids.error : help ? ids.help : void 0;
|
|
27
|
+
const ctx = {
|
|
28
|
+
id,
|
|
29
|
+
labelId: ids.label,
|
|
30
|
+
describedBy,
|
|
31
|
+
invalid: Boolean(error),
|
|
32
|
+
required: Boolean(required)
|
|
33
|
+
};
|
|
34
|
+
return /* @__PURE__ */ jsx(FieldContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxs(
|
|
35
|
+
"div",
|
|
36
|
+
{
|
|
37
|
+
ref,
|
|
38
|
+
className: clsx("flex min-w-0 flex-col gap-1u font-sans normal-case", className),
|
|
39
|
+
...props,
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsxs(
|
|
42
|
+
"label",
|
|
43
|
+
{
|
|
44
|
+
ref: labelRef,
|
|
45
|
+
id: ids.label,
|
|
46
|
+
htmlFor: id,
|
|
47
|
+
className: "m-0 min-w-0 oprt-wrap-anywhere text-oprt-base font-medium text-oprt-text",
|
|
48
|
+
children: [
|
|
49
|
+
label,
|
|
50
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " *" })
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
),
|
|
54
|
+
children,
|
|
55
|
+
error ? /* @__PURE__ */ jsx(
|
|
56
|
+
"p",
|
|
57
|
+
{
|
|
58
|
+
id: ids.error,
|
|
59
|
+
className: "m-0 min-w-0 oprt-wrap-anywhere text-oprt-base text-oprt-error",
|
|
60
|
+
role: "alert",
|
|
61
|
+
children: error
|
|
62
|
+
}
|
|
63
|
+
) : help ? /* @__PURE__ */ jsx(
|
|
64
|
+
"p",
|
|
65
|
+
{
|
|
66
|
+
id: ids.help,
|
|
67
|
+
className: "m-0 min-w-0 oprt-wrap-anywhere text-oprt-base text-oprt-text-dim",
|
|
68
|
+
children: help
|
|
69
|
+
}
|
|
70
|
+
) : null
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
) });
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
Field.displayName = "Field";
|
|
77
|
+
export {
|
|
78
|
+
Field,
|
|
79
|
+
useFieldContext,
|
|
80
|
+
useOptionalFieldContext
|
|
81
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/Field/Field.manifest.ts
|
|
2
|
+
var FieldManifest = {
|
|
3
|
+
Field: {
|
|
4
|
+
description: "Form field wrapper providing label, help text, and error display. Labels, help, errors, and entered values preserve their original casing. A required Field makes its control required. NumberInput, CoordinateInput and MultiSelect carry their own label and are not placed in a Field.",
|
|
5
|
+
props: {
|
|
6
|
+
controlId: {
|
|
7
|
+
type: "string",
|
|
8
|
+
description: "Stable child control ID used by the label and context. Native id remains the wrapper ID; generated control IDs are the default."
|
|
9
|
+
},
|
|
10
|
+
label: { type: "string", required: true },
|
|
11
|
+
help: { type: "string" },
|
|
12
|
+
error: { type: "string" },
|
|
13
|
+
required: {
|
|
14
|
+
type: "boolean",
|
|
15
|
+
default: false,
|
|
16
|
+
description: "Marks the label and makes the control inside required: announced as required, and the browser stops a native submission while it is empty. A form that validates itself sets noValidate on the form, which keeps the announcement. A control's own required={false} wins."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
slots: {
|
|
20
|
+
children: {
|
|
21
|
+
type: "Input | Textarea | Select | ComboBox | Checkbox | RadioGroup | Toggle | Slider",
|
|
22
|
+
required: true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
composable_with: ["Card", "FormSection", "FormErrorSummary"],
|
|
26
|
+
never_inside: ["Field", "Button"],
|
|
27
|
+
example: '<Field label="ENDPOINT" error="Required">\n <Input placeholder="api.system.io" />\n</Field>'
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export {
|
|
31
|
+
FieldManifest
|
|
32
|
+
};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/FileUpload/FileUpload.tsx
|
|
4
|
+
import {
|
|
5
|
+
forwardRef,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState
|
|
9
|
+
} from "react";
|
|
10
|
+
import { Button as AriaButton, DropZone, FileTrigger } from "react-aria-components";
|
|
11
|
+
import { cva } from "class-variance-authority";
|
|
12
|
+
import clsx from "clsx";
|
|
13
|
+
import { Button } from "../Button/Button.js";
|
|
14
|
+
import { NUMBER_UNIT_SPACE } from "../_internal/bytes.js";
|
|
15
|
+
import { joinIds, usePartIds } from "../_internal/fieldIds.js";
|
|
16
|
+
import { useMergedRefs } from "../_internal/mergeRefs.js";
|
|
17
|
+
import { useIsMounted } from "../_internal/useIsMounted.js";
|
|
18
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
var uploadStyles = cva(
|
|
20
|
+
"flex min-w-0 flex-col gap-2u font-sans text-oprt-base normal-case text-oprt-text"
|
|
21
|
+
);
|
|
22
|
+
var dropStyles = cva(
|
|
23
|
+
"flex min-w-0 flex-col items-start gap-2u border border-dashed border-oprt-border bg-oprt-surface-1 p-3u data-[drop-target]:border-oprt-accent data-[focus-visible]:border-oprt-border-focus data-[focus-visible]:shadow-oprt-focus"
|
|
24
|
+
);
|
|
25
|
+
var validAccept = (token) => /^\.[a-z0-9][a-z0-9._+-]*$/i.test(token) || /^(?:[a-z0-9!#$&^_.+-]+\/(?:[a-z0-9!#$&^_.+-]+|\*)|\*\/\*)$/i.test(token);
|
|
26
|
+
var FileUpload = forwardRef(
|
|
27
|
+
({
|
|
28
|
+
label,
|
|
29
|
+
description,
|
|
30
|
+
accept,
|
|
31
|
+
multiple = false,
|
|
32
|
+
maxFiles,
|
|
33
|
+
maxFileSizeBytes,
|
|
34
|
+
disabled = false,
|
|
35
|
+
onFiles,
|
|
36
|
+
onReject,
|
|
37
|
+
className,
|
|
38
|
+
"aria-labelledby": labelledBy,
|
|
39
|
+
"aria-describedby": describedBy,
|
|
40
|
+
...props
|
|
41
|
+
}, ref) => {
|
|
42
|
+
const root = useRef(null);
|
|
43
|
+
const mergedRef = useMergedRefs(root, ref);
|
|
44
|
+
const ids = usePartIds(["label", "description", "configuration"], {
|
|
45
|
+
id: props.id,
|
|
46
|
+
readRendered: () => root.current?.getAttribute("data-oprt-ids")
|
|
47
|
+
});
|
|
48
|
+
const [issues, setIssues] = useState([]);
|
|
49
|
+
const [reading, setReading] = useState(false);
|
|
50
|
+
const [feedback, setFeedback] = useState("");
|
|
51
|
+
const isMounted = useIsMounted();
|
|
52
|
+
const generation = useRef(0);
|
|
53
|
+
const types = accept?.map((token) => token.trim().toLowerCase()) ?? [];
|
|
54
|
+
const configurationError = accept?.some((token) => !validAccept(token.trim())) ? "Invalid accept configuration. Use file extensions or MIME types." : maxFiles !== void 0 && (!Number.isSafeInteger(maxFiles) || maxFiles < 1) ? "Invalid maxFiles configuration. Supply a positive integer." : maxFileSizeBytes !== void 0 && (!Number.isSafeInteger(maxFileSizeBytes) || maxFileSizeBytes < 0) ? "Invalid maxFileSizeBytes configuration. Supply a nonnegative integer." : "";
|
|
55
|
+
const signature = JSON.stringify([types, multiple, String(maxFiles), String(maxFileSizeBytes)]);
|
|
56
|
+
const latest = useRef({ disabled, configurationError, signature, onFiles, onReject });
|
|
57
|
+
latest.current = { disabled, configurationError, signature, onFiles, onReject };
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const requests = generation;
|
|
60
|
+
return () => {
|
|
61
|
+
requests.current++;
|
|
62
|
+
};
|
|
63
|
+
}, []);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
generation.current++;
|
|
66
|
+
setReading(false);
|
|
67
|
+
}, [signature, disabled]);
|
|
68
|
+
async function select(candidates) {
|
|
69
|
+
if (!candidates.length || latest.current.disabled || latest.current.configurationError)
|
|
70
|
+
return;
|
|
71
|
+
const request = ++generation.current;
|
|
72
|
+
const constraints = signature;
|
|
73
|
+
setIssues([]);
|
|
74
|
+
setFeedback("");
|
|
75
|
+
setReading(true);
|
|
76
|
+
const results = await Promise.allSettled(
|
|
77
|
+
candidates.map(
|
|
78
|
+
async (candidate) => "issue" in candidate ? candidate : { file: await candidate.read() }
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
if (!isMounted() || generation.current !== request || latest.current.disabled || latest.current.configurationError || latest.current.signature !== constraints)
|
|
82
|
+
return;
|
|
83
|
+
const accepted = [];
|
|
84
|
+
const rejected = [];
|
|
85
|
+
const countLimit = multiple ? maxFiles ?? Infinity : 1;
|
|
86
|
+
let fileCount = 0;
|
|
87
|
+
results.forEach((result, index) => {
|
|
88
|
+
const candidate = candidates[index];
|
|
89
|
+
if (result.status === "rejected") {
|
|
90
|
+
rejected.push({
|
|
91
|
+
name: "name" in candidate ? candidate.name : "File",
|
|
92
|
+
code: "read",
|
|
93
|
+
message: "File could not be read."
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if ("issue" in result.value) {
|
|
98
|
+
rejected.push(result.value.issue);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const value = result.value.file;
|
|
102
|
+
fileCount++;
|
|
103
|
+
if (fileCount > countLimit)
|
|
104
|
+
rejected.push({
|
|
105
|
+
name: value.name,
|
|
106
|
+
code: "count",
|
|
107
|
+
message: `Choose at most ${countLimit} file${countLimit === 1 ? "" : "s"} per selection.`
|
|
108
|
+
});
|
|
109
|
+
else if (types.length && !types.some(
|
|
110
|
+
(type) => type === "*/*" || (type.startsWith(".") ? value.name.toLowerCase().endsWith(type) : type.endsWith("/*") ? value.type.toLowerCase().startsWith(type.slice(0, -1)) : value.type.toLowerCase() === type)
|
|
111
|
+
))
|
|
112
|
+
rejected.push({ name: value.name, code: "type", message: "File type is not accepted." });
|
|
113
|
+
else if (maxFileSizeBytes !== void 0 && value.size > maxFileSizeBytes)
|
|
114
|
+
rejected.push({
|
|
115
|
+
name: value.name,
|
|
116
|
+
code: "size",
|
|
117
|
+
// The limit and its unit stay on one line (R4, design call DC-11).
|
|
118
|
+
message: `File exceeds ${maxFileSizeBytes}${NUMBER_UNIT_SPACE}bytes.`
|
|
119
|
+
});
|
|
120
|
+
else accepted.push(value);
|
|
121
|
+
});
|
|
122
|
+
setReading(false);
|
|
123
|
+
setIssues(rejected);
|
|
124
|
+
setFeedback(
|
|
125
|
+
`${accepted.length} file${accepted.length === 1 ? "" : "s"} selected locally${rejected.length ? `; ${rejected.length} rejected` : ""}.`
|
|
126
|
+
);
|
|
127
|
+
if (accepted.length) latest.current.onFiles(Object.freeze(accepted));
|
|
128
|
+
if (rejected.length) latest.current.onReject?.(Object.freeze(rejected));
|
|
129
|
+
}
|
|
130
|
+
function dropped(items) {
|
|
131
|
+
return select(
|
|
132
|
+
items.map(
|
|
133
|
+
(item) => item.kind === "file" ? { name: item.name, read: () => item.getFile() } : {
|
|
134
|
+
issue: {
|
|
135
|
+
name: item.kind === "directory" ? item.name : "Dropped item",
|
|
136
|
+
code: item.kind === "directory" ? "directory" : "unsupported",
|
|
137
|
+
message: item.kind === "directory" ? "Directories are not supported. Choose individual files." : "Only files are supported."
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const blocked = disabled || !!configurationError;
|
|
144
|
+
const hasDescription = description != null && typeof description !== "boolean";
|
|
145
|
+
return /* @__PURE__ */ jsxs(
|
|
146
|
+
"div",
|
|
147
|
+
{
|
|
148
|
+
...props,
|
|
149
|
+
ref: mergedRef,
|
|
150
|
+
role: "group",
|
|
151
|
+
"data-oprt-ids": ids.base,
|
|
152
|
+
"aria-labelledby": joinIds(ids.label, labelledBy),
|
|
153
|
+
"aria-describedby": joinIds(
|
|
154
|
+
hasDescription && ids.description,
|
|
155
|
+
configurationError && ids.configuration,
|
|
156
|
+
describedBy
|
|
157
|
+
),
|
|
158
|
+
className: clsx(uploadStyles(), className),
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ jsx("p", { id: ids.label, className: "m-0 oprt-wrap-anywhere font-medium uppercase tracking-oprt-sm", children: label }),
|
|
161
|
+
hasDescription && /* @__PURE__ */ jsx(
|
|
162
|
+
"div",
|
|
163
|
+
{
|
|
164
|
+
id: ids.description,
|
|
165
|
+
className: "min-w-0 oprt-wrap-anywhere text-oprt-text-dim [&_p]:m-0",
|
|
166
|
+
children: description
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
/* @__PURE__ */ jsxs(
|
|
170
|
+
DropZone,
|
|
171
|
+
{
|
|
172
|
+
"aria-label": `${label} drop area`,
|
|
173
|
+
isDisabled: blocked,
|
|
174
|
+
className: dropStyles(),
|
|
175
|
+
onDrop: (event) => {
|
|
176
|
+
void dropped(event.items);
|
|
177
|
+
},
|
|
178
|
+
getDropOperation: (_types, operations) => operations.includes("copy") ? "copy" : "cancel",
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsx("p", { className: clsx("m-0", blocked && "text-oprt-text-dim"), children: "Drop files here or choose files." }),
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
FileTrigger,
|
|
183
|
+
{
|
|
184
|
+
allowsMultiple: multiple,
|
|
185
|
+
...accept ? { acceptedFileTypes: accept } : {},
|
|
186
|
+
onSelect: (files) => {
|
|
187
|
+
void select(
|
|
188
|
+
Array.from(files ?? []).map((file) => ({
|
|
189
|
+
name: file.name,
|
|
190
|
+
read: async () => file
|
|
191
|
+
}))
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
children: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "secondary", children: /* @__PURE__ */ jsx(AriaButton, { isDisabled: blocked, children: "Choose files" }) })
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
configurationError && /* @__PURE__ */ jsx("p", { id: ids.configuration, role: "alert", className: "m-0 text-oprt-error", children: configurationError }),
|
|
201
|
+
issues.length > 0 && /* @__PURE__ */ jsx("ul", { className: "m-0 flex min-w-0 list-disc flex-col gap-1u pl-3u text-oprt-error", children: issues.map((issue, index) => /* @__PURE__ */ jsxs("li", { className: "oprt-wrap-anywhere", children: [
|
|
202
|
+
issue.name,
|
|
203
|
+
": ",
|
|
204
|
+
issue.message
|
|
205
|
+
] }, index)) }),
|
|
206
|
+
/* @__PURE__ */ jsx("p", { role: "status", "aria-atomic": "true", className: "m-0 text-oprt-text-dim", children: reading ? "Reading selected files\u2026" : feedback })
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
FileUpload.displayName = "FileUpload";
|
|
213
|
+
export {
|
|
214
|
+
FileUpload
|
|
215
|
+
};
|