@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,48 @@
|
|
|
1
|
+
// src/FileUpload/FileUpload.manifest.ts
|
|
2
|
+
var FileUploadManifest = {
|
|
3
|
+
FileUpload: {
|
|
4
|
+
description: "Choose, drop or paste files with bounded validation and readable rejection feedback.",
|
|
5
|
+
props: {
|
|
6
|
+
label: {
|
|
7
|
+
type: "string",
|
|
8
|
+
required: true,
|
|
9
|
+
description: "Visible name for the file selection group."
|
|
10
|
+
},
|
|
11
|
+
description: { type: "node", description: "Optional guidance associated with the group." },
|
|
12
|
+
accept: {
|
|
13
|
+
type: "array",
|
|
14
|
+
description: "Allowed extensions (.csv), MIME types (text/csv), or MIME wildcards (image/*). Case-insensitive, OR matching. Empty means any type. Browser hints do not validate content."
|
|
15
|
+
},
|
|
16
|
+
multiple: { type: "boolean", default: false },
|
|
17
|
+
maxFiles: {
|
|
18
|
+
type: "number",
|
|
19
|
+
description: "Positive integer limit per selection batch. Single-file mode always permits at most one file. Files are considered in input order, including files rejected by type/size."
|
|
20
|
+
},
|
|
21
|
+
maxFileSizeBytes: {
|
|
22
|
+
type: "number",
|
|
23
|
+
description: "Inclusive nonnegative integer byte limit. Zero allows only empty files. Omitted means unlimited."
|
|
24
|
+
},
|
|
25
|
+
disabled: {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
default: false,
|
|
28
|
+
description: "Blocks all input paths and invalidates in-flight file resolution."
|
|
29
|
+
},
|
|
30
|
+
onFiles: {
|
|
31
|
+
type: "function",
|
|
32
|
+
required: true,
|
|
33
|
+
description: "Receives accepted readonly File[] in input order. Selection does not establish upload or persistence. No callback for chooser cancellation or an empty accepted set."
|
|
34
|
+
},
|
|
35
|
+
onReject: {
|
|
36
|
+
type: "function",
|
|
37
|
+
description: "Receives readonly FileRejection[]: name, code (type/size/count/directory/unsupported/read), message. Rejections are also displayed."
|
|
38
|
+
},
|
|
39
|
+
className: { type: "string" }
|
|
40
|
+
},
|
|
41
|
+
composable_with: ["UploadQueue", "AttachmentPreview", "FormSection"],
|
|
42
|
+
never_inside: ["Button"],
|
|
43
|
+
example: '<FileUpload label="Equipment import" accept={[".csv"]} maxFileSizeBytes={1048576} onFiles={selectFiles} onReject={reportIssues} />'
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
FileUploadManifest
|
|
48
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/FilterBar/FilterBar.tsx
|
|
4
|
+
import { ToggleButtonGroup, ToggleButton } from "react-aria-components";
|
|
5
|
+
import { mergeProps } from "react-aria";
|
|
6
|
+
import { filterDOMProps } from "react-aria/filterDOMProps";
|
|
7
|
+
import { forwardRef, useEffect, useRef, useState } from "react";
|
|
8
|
+
import clsx from "clsx";
|
|
9
|
+
import { useMergedRefs } from "../_internal/mergeRefs.js";
|
|
10
|
+
import { useRestoreFocusOnRemoval } from "../_internal/useRestoreFocusOnRemoval.js";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var itemStyles = [
|
|
13
|
+
// Design call DC-8 and its ruling: the height is a minimum, so a label that wraps grows its filter
|
|
14
|
+
// instead of spilling out, and the label is centered on one line or several. The padding is what
|
|
15
|
+
// is left of 32 px around one line and the border, so a one-line filter keeps its exact height,
|
|
16
|
+
// and `h-fit` keeps a row that stretches its items from growing it to its tallest neighbor. An
|
|
17
|
+
// unbroken label breaks anywhere instead of widening the bar (R4).
|
|
18
|
+
"inline-flex h-fit min-h-oprt-md min-w-0 max-w-full flex-col items-center justify-center whitespace-normal text-center oprt-wrap-anywhere",
|
|
19
|
+
"px-2u py-[calc((var(--oprt-height-md)-2px-var(--oprt-line-base))/2)]",
|
|
20
|
+
// The boundary of an unselected filter is the control outline (design call DC-3).
|
|
21
|
+
"border border-oprt-border-control text-oprt-base font-medium uppercase tracking-oprt-caps text-oprt-text-dim",
|
|
22
|
+
// Hover brightens an enabled, unselected filter only: a disabled one keeps its look.
|
|
23
|
+
"data-[hovered]:[&:not([data-selected])]:text-oprt-text",
|
|
24
|
+
"data-[selected]:text-oprt-bg data-[selected]:bg-oprt-accent data-[selected]:border-oprt-accent-light",
|
|
25
|
+
// The system's focus ring replaces the browser's own.
|
|
26
|
+
"focus-visible:outline-hidden data-[focus-visible]:border-oprt-border-focus data-[focus-visible]:shadow-oprt-focus",
|
|
27
|
+
"disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-oprt-fast",
|
|
28
|
+
// Forced colors replace backgrounds and borders with system colors and drop the shadow, so the
|
|
29
|
+
// selected filter would look like the others and focus would vanish. Selection is redrawn from
|
|
30
|
+
// Highlight; a disabled selected filter stays filled, in GrayText (`:disabled` outranks the
|
|
31
|
+
// enabled rule); focus becomes an outline.
|
|
32
|
+
"forced-colors:data-[selected]:[forced-color-adjust:none] forced-colors:data-[selected]:bg-[color:Highlight] forced-colors:data-[selected]:text-[color:HighlightText] forced-colors:data-[selected]:border-[color:Highlight]",
|
|
33
|
+
"forced-colors:data-[selected]:disabled:bg-[color:GrayText] forced-colors:data-[selected]:disabled:text-[color:Canvas] forced-colors:data-[selected]:disabled:border-[color:GrayText]",
|
|
34
|
+
"forced-colors:data-[focus-visible]:outline-solid forced-colors:data-[focus-visible]:outline-2 forced-colors:data-[focus-visible]:outline-offset-2 forced-colors:data-[focus-visible]:outline-[color:CanvasText]"
|
|
35
|
+
].join(" ");
|
|
36
|
+
var UNAVAILABLE = "Unavailable";
|
|
37
|
+
var shownAs = (value) => value === "" ? "\u2014" : value;
|
|
38
|
+
function toKeys(value) {
|
|
39
|
+
if (typeof value !== "string") return value;
|
|
40
|
+
return value === "" ? [] : [value];
|
|
41
|
+
}
|
|
42
|
+
var reported = /* @__PURE__ */ new Set();
|
|
43
|
+
function report(mistake, prop, received) {
|
|
44
|
+
if (process.env.NODE_ENV === "production") return;
|
|
45
|
+
const key = `${mistake}\0${prop}\0${received}`;
|
|
46
|
+
if (reported.has(key)) return;
|
|
47
|
+
reported.add(key);
|
|
48
|
+
const [error, suggestion] = mistake === "unknown value" ? [
|
|
49
|
+
"UNKNOWN_FILTER_VALUE",
|
|
50
|
+
"The selection names a value that is not in `filters`. FilterBar shows it as a selected filter marked unavailable, at the end of the bar, which the operator can remove. Add it to `filters` if it is still offered, or leave it out of the selection."
|
|
51
|
+
] : mistake === "duplicate filter" ? [
|
|
52
|
+
"DUPLICATE_FILTER",
|
|
53
|
+
"Each filter label must be unique: FilterBar shows a repeated label once. Remove the duplicate from `filters`."
|
|
54
|
+
] : [
|
|
55
|
+
"PROP_NOT_APPLIED",
|
|
56
|
+
prop === "role" ? "FilterBar's group is a radio group in single mode and a toolbar in multiple mode; a role is not applied." : prop === "aria-orientation" ? "FilterBar's filters wrap onto rows and arrow keys follow reading order; aria-orientation is not applied." : "FilterBar draws its own filters; dangerouslySetInnerHTML is not applied. Supply them as `filters`."
|
|
57
|
+
];
|
|
58
|
+
console.error(
|
|
59
|
+
JSON.stringify({ component: "FilterBar", error, prop, received, suggestion }, null, 2)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
var NOT_APPLIED = ["role", "aria-orientation", "dangerouslySetInnerHTML"];
|
|
63
|
+
var buttonsIn = (root) => root ? Array.from(root.querySelectorAll("button")) : [];
|
|
64
|
+
var FilterBar = forwardRef((componentProps, ref) => {
|
|
65
|
+
const {
|
|
66
|
+
className,
|
|
67
|
+
filters,
|
|
68
|
+
value,
|
|
69
|
+
defaultValue,
|
|
70
|
+
onValueChange: _onValueChange,
|
|
71
|
+
multiple = false,
|
|
72
|
+
ariaLabel = "Filters",
|
|
73
|
+
disabled = false,
|
|
74
|
+
...props
|
|
75
|
+
} = componentProps;
|
|
76
|
+
const root = useRef(null);
|
|
77
|
+
const mergedRef = useMergedRefs(root, ref);
|
|
78
|
+
const [ownSelection, setOwnSelection] = useState(
|
|
79
|
+
() => toKeys(defaultValue ?? "")
|
|
80
|
+
);
|
|
81
|
+
const selected = value !== void 0 ? toKeys(value) : ownSelection;
|
|
82
|
+
const offered = [...new Set(filters)];
|
|
83
|
+
const duplicates = [
|
|
84
|
+
...new Set(filters.filter((filter, index) => filters.indexOf(filter) !== index))
|
|
85
|
+
];
|
|
86
|
+
const unavailable = [...new Set(selected)].filter((key) => !offered.includes(key));
|
|
87
|
+
const sourceProp = value !== void 0 ? "value" : "defaultValue";
|
|
88
|
+
const unavailableKey = JSON.stringify(unavailable);
|
|
89
|
+
const duplicatesKey = JSON.stringify(duplicates);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (process.env.NODE_ENV === "production") return;
|
|
92
|
+
for (const key of JSON.parse(unavailableKey))
|
|
93
|
+
report("unknown value", sourceProp, key);
|
|
94
|
+
for (const key of JSON.parse(duplicatesKey))
|
|
95
|
+
report("duplicate filter", "filters", key);
|
|
96
|
+
}, [unavailableKey, duplicatesKey, sourceProp]);
|
|
97
|
+
function changeSelection(keys) {
|
|
98
|
+
const next = Array.from(keys, String);
|
|
99
|
+
const current = new Set(selected);
|
|
100
|
+
if (next.length === current.size && next.every((key) => current.has(key))) return;
|
|
101
|
+
if (value === void 0) setOwnSelection(next);
|
|
102
|
+
if (componentProps.multiple) componentProps.onValueChange?.(next);
|
|
103
|
+
else componentProps.onValueChange?.(next[0] ?? "");
|
|
104
|
+
}
|
|
105
|
+
const restore = useRestoreFocusOnRemoval(root, {
|
|
106
|
+
track: (element) => {
|
|
107
|
+
const index = buttonsIn(root.current).indexOf(element);
|
|
108
|
+
return index >= 0 ? { index } : null;
|
|
109
|
+
},
|
|
110
|
+
findTarget: ({ index }) => {
|
|
111
|
+
const enabled = buttonsIn(root.current).filter((button) => !button.disabled);
|
|
112
|
+
return enabled[Math.min(index, enabled.length - 1)] ?? null;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
const forwarded = filterDOMProps(props, {
|
|
116
|
+
global: true,
|
|
117
|
+
labelable: true
|
|
118
|
+
});
|
|
119
|
+
const dropped = { ...props };
|
|
120
|
+
for (const name of [...Object.keys(forwarded), ...NOT_APPLIED])
|
|
121
|
+
delete dropped[name];
|
|
122
|
+
const notApplied = NOT_APPLIED.filter((name) => props[name] !== void 0).join(" ");
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (process.env.NODE_ENV === "production") return;
|
|
125
|
+
for (const name of notApplied ? notApplied.split(" ") : []) report("not applied", name, name);
|
|
126
|
+
}, [notApplied]);
|
|
127
|
+
return /* @__PURE__ */ jsxs(
|
|
128
|
+
ToggleButtonGroup,
|
|
129
|
+
{
|
|
130
|
+
ref: mergedRef,
|
|
131
|
+
isDisabled: disabled,
|
|
132
|
+
"aria-label": ariaLabel,
|
|
133
|
+
selectionMode: multiple ? "multiple" : "single",
|
|
134
|
+
disallowEmptySelection: !multiple,
|
|
135
|
+
selectedKeys: selected,
|
|
136
|
+
onSelectionChange: changeSelection,
|
|
137
|
+
className: clsx("flex min-w-0 max-w-full flex-wrap gap-1u font-sans", className),
|
|
138
|
+
...props,
|
|
139
|
+
render: (domProps) => /* @__PURE__ */ jsx(
|
|
140
|
+
"div",
|
|
141
|
+
{
|
|
142
|
+
...mergeProps(dropped, domProps, {
|
|
143
|
+
onFocusCapture: restore.onFocusCapture,
|
|
144
|
+
onBlurCapture: restore.onBlurCapture
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
children: [
|
|
149
|
+
offered.map((filter) => /* @__PURE__ */ jsx(ToggleButton, { id: filter, className: itemStyles, children: filter }, filter)),
|
|
150
|
+
unavailable.map((key) => (
|
|
151
|
+
// The name joins the value and its cue with a pause; it contains the visible text.
|
|
152
|
+
/* @__PURE__ */ jsxs(
|
|
153
|
+
ToggleButton,
|
|
154
|
+
{
|
|
155
|
+
id: key,
|
|
156
|
+
"aria-label": `${shownAs(key)}, ${UNAVAILABLE}`,
|
|
157
|
+
className: itemStyles,
|
|
158
|
+
children: [
|
|
159
|
+
shownAs(key),
|
|
160
|
+
/* @__PURE__ */ jsx("span", { className: "font-normal normal-case tracking-normal", children: UNAVAILABLE })
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
key
|
|
164
|
+
)
|
|
165
|
+
))
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
FilterBar.displayName = "FilterBar";
|
|
171
|
+
export {
|
|
172
|
+
FilterBar
|
|
173
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// src/FilterBar/FilterBar.manifest.ts
|
|
2
|
+
var FilterBarManifest = {
|
|
3
|
+
FilterBar: {
|
|
4
|
+
description: "Toggle-button filters for a view, wrapping onto more rows when they do not fit. Single-select by default; set multiple for multi-select.",
|
|
5
|
+
props: {
|
|
6
|
+
filters: {
|
|
7
|
+
type: "array",
|
|
8
|
+
required: true,
|
|
9
|
+
description: "Readonly string[] of filter labels, each shown once, in order."
|
|
10
|
+
},
|
|
11
|
+
value: {
|
|
12
|
+
type: "union",
|
|
13
|
+
types: ["string", "array"],
|
|
14
|
+
description: "Controlled selection: string in single mode; readonly string[] when multiple=true. Use an empty string or array to clear the corresponding mode. A selected value that is not in filters shows at the end of the bar as a selected filter marked unavailable, which the operator can remove."
|
|
15
|
+
},
|
|
16
|
+
defaultValue: {
|
|
17
|
+
type: "union",
|
|
18
|
+
types: ["string", "array"],
|
|
19
|
+
description: "Initial uncontrolled selection: string in single mode; readonly string[] when multiple=true."
|
|
20
|
+
},
|
|
21
|
+
multiple: {
|
|
22
|
+
type: "boolean",
|
|
23
|
+
default: false,
|
|
24
|
+
description: "When true, value, defaultValue, and onValueChange use string[] and a selected filter can be cleared; otherwise they use string and the filters are radios, so the active filter stays selected until another is chosen."
|
|
25
|
+
},
|
|
26
|
+
ariaLabel: {
|
|
27
|
+
type: "string",
|
|
28
|
+
default: "Filters",
|
|
29
|
+
description: "Accessible name for the group."
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
default: false,
|
|
34
|
+
description: "Disable pointer and keyboard selection while retaining the active filters."
|
|
35
|
+
},
|
|
36
|
+
onValueChange: {
|
|
37
|
+
type: "function",
|
|
38
|
+
description: "Receives the active string in single mode or the complete string[] selection when multiple=true."
|
|
39
|
+
},
|
|
40
|
+
className: { type: "string" }
|
|
41
|
+
},
|
|
42
|
+
composable_with: ["Card"],
|
|
43
|
+
never_inside: ["Button", "Badge"],
|
|
44
|
+
example: '<FilterBar filters={["ALL","FRIENDLY","HOSTILE","NEUTRAL","UNKNOWN"]} defaultValue="ALL" />'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
export {
|
|
48
|
+
FilterBarManifest
|
|
49
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/FormErrorSummary/FormErrorSummary.tsx
|
|
4
|
+
import { forwardRef, useRef } from "react";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import clsx from "clsx";
|
|
7
|
+
import { joinIds, usePartIds } from "../_internal/fieldIds.js";
|
|
8
|
+
import { useMergedRefs } from "../_internal/mergeRefs.js";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var summaryStyles = cva(
|
|
11
|
+
"flex min-w-0 flex-col gap-2u border border-oprt-error bg-oprt-surface-1 p-3u font-sans text-oprt-base normal-case tracking-normal text-oprt-text outline-hidden focus-visible:shadow-oprt-focus"
|
|
12
|
+
);
|
|
13
|
+
var errorStyles = cva(
|
|
14
|
+
"inline-flex min-h-3u min-w-3u max-w-full items-center border border-transparent px-1u py-0.5u text-left text-oprt-base font-medium normal-case tracking-normal text-oprt-text underline underline-offset-2 hover:text-oprt-accent outline-hidden focus-visible:border-oprt-border-focus focus-visible:shadow-oprt-focus oprt-wrap-anywhere"
|
|
15
|
+
);
|
|
16
|
+
var FormErrorSummary = forwardRef(
|
|
17
|
+
({
|
|
18
|
+
errors,
|
|
19
|
+
title = "Check these fields",
|
|
20
|
+
onErrorSelect,
|
|
21
|
+
className,
|
|
22
|
+
tabIndex = -1,
|
|
23
|
+
"aria-labelledby": labelledBy,
|
|
24
|
+
...props
|
|
25
|
+
}, ref) => {
|
|
26
|
+
const root = useRef(null);
|
|
27
|
+
const mergedRef = useMergedRefs(root, ref);
|
|
28
|
+
const ids = usePartIds(["title"], {
|
|
29
|
+
id: props.id,
|
|
30
|
+
readRendered: () => root.current?.getAttribute("data-oprt-ids")
|
|
31
|
+
});
|
|
32
|
+
return /* @__PURE__ */ jsxs(
|
|
33
|
+
"section",
|
|
34
|
+
{
|
|
35
|
+
...props,
|
|
36
|
+
ref: mergedRef,
|
|
37
|
+
tabIndex,
|
|
38
|
+
"data-oprt-ids": ids.base,
|
|
39
|
+
"aria-labelledby": joinIds(ids.title, labelledBy),
|
|
40
|
+
className: clsx(summaryStyles(), className),
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsx(
|
|
43
|
+
"h2",
|
|
44
|
+
{
|
|
45
|
+
id: ids.title,
|
|
46
|
+
className: "m-0 min-w-0 oprt-wrap-anywhere text-oprt-base font-medium uppercase tracking-oprt-sm text-oprt-error",
|
|
47
|
+
children: title
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx("ul", { className: "m-0 flex min-w-0 list-none flex-col gap-1u p-0", children: errors.map((error) => /* @__PURE__ */ jsx("li", { className: "m-0 min-w-0 p-0", children: /* @__PURE__ */ jsx(
|
|
51
|
+
"button",
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
className: errorStyles(),
|
|
55
|
+
onClick: (event) => {
|
|
56
|
+
if (onErrorSelect) onErrorSelect(error);
|
|
57
|
+
else event.currentTarget.ownerDocument.getElementById(error.targetId)?.focus();
|
|
58
|
+
},
|
|
59
|
+
children: error.message
|
|
60
|
+
}
|
|
61
|
+
) }, error.id)) })
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
FormErrorSummary.displayName = "FormErrorSummary";
|
|
68
|
+
export {
|
|
69
|
+
FormErrorSummary
|
|
70
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/FormErrorSummary/FormErrorSummary.manifest.ts
|
|
2
|
+
var FormErrorSummaryManifest = {
|
|
3
|
+
FormErrorSummary: {
|
|
4
|
+
description: "Focusable error summary with actions that reveal or focus invalid form controls.",
|
|
5
|
+
props: {
|
|
6
|
+
errors: {
|
|
7
|
+
type: "array",
|
|
8
|
+
required: true,
|
|
9
|
+
description: "Readonly errors with stable unique id, readable message and targetId for the control."
|
|
10
|
+
},
|
|
11
|
+
title: {
|
|
12
|
+
type: "string",
|
|
13
|
+
default: "Check these fields",
|
|
14
|
+
description: "Visible heading that names the summary section."
|
|
15
|
+
},
|
|
16
|
+
onErrorSelect: {
|
|
17
|
+
type: "function",
|
|
18
|
+
description: "Optional reveal/focus handler receiving the selected error. Replaces direct target focus; reveal hidden controls before focusing them after render."
|
|
19
|
+
},
|
|
20
|
+
className: { type: "string" }
|
|
21
|
+
},
|
|
22
|
+
composable_with: ["Field", "FormSection", "Input"],
|
|
23
|
+
never_inside: ["Button"],
|
|
24
|
+
example: "<FormErrorSummary ref={summaryRef} errors={errors} onErrorSelect={revealAndFocus} />"
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
FormErrorSummaryManifest
|
|
29
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/FormSection/FormSection.tsx
|
|
4
|
+
import { forwardRef, useRef } from "react";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import clsx from "clsx";
|
|
7
|
+
import { joinIds, usePartIds } from "../_internal/fieldIds.js";
|
|
8
|
+
import { useMergedRefs } from "../_internal/mergeRefs.js";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var sectionStyles = cva(
|
|
11
|
+
"m-0 min-w-0 border border-oprt-border bg-oprt-surface-1 p-3u font-sans text-oprt-base normal-case tracking-normal text-oprt-text"
|
|
12
|
+
);
|
|
13
|
+
var FormSection = forwardRef(
|
|
14
|
+
({ legend, description, children, className, "aria-describedby": describedBy, ...props }, ref) => {
|
|
15
|
+
const root = useRef(null);
|
|
16
|
+
const mergedRef = useMergedRefs(root, ref);
|
|
17
|
+
const ids = usePartIds(["description"], {
|
|
18
|
+
id: props.id,
|
|
19
|
+
readRendered: () => root.current?.getAttribute("data-oprt-ids")
|
|
20
|
+
});
|
|
21
|
+
const hasDescription = description != null && typeof description !== "boolean";
|
|
22
|
+
return /* @__PURE__ */ jsxs(
|
|
23
|
+
"fieldset",
|
|
24
|
+
{
|
|
25
|
+
...props,
|
|
26
|
+
ref: mergedRef,
|
|
27
|
+
"data-oprt-ids": ids.base,
|
|
28
|
+
"aria-describedby": joinIds(hasDescription && ids.description, describedBy),
|
|
29
|
+
className: clsx(sectionStyles(), className),
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx("legend", { className: "m-0 max-w-full oprt-wrap-anywhere px-1u text-oprt-base font-medium uppercase tracking-oprt-sm", children: legend }),
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-2u", children: [
|
|
33
|
+
hasDescription && /* @__PURE__ */ jsx(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
id: ids.description,
|
|
37
|
+
className: "min-w-0 oprt-wrap-anywhere text-oprt-text-dim [&_p]:m-0",
|
|
38
|
+
children: description
|
|
39
|
+
}
|
|
40
|
+
),
|
|
41
|
+
children
|
|
42
|
+
] })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
FormSection.displayName = "FormSection";
|
|
49
|
+
export {
|
|
50
|
+
FormSection
|
|
51
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/FormSection/FormSection.manifest.ts
|
|
2
|
+
var FormSectionManifest = {
|
|
3
|
+
FormSection: {
|
|
4
|
+
description: "Native fieldset with a legend, optional description and supplied form controls.",
|
|
5
|
+
props: {
|
|
6
|
+
legend: {
|
|
7
|
+
type: "string",
|
|
8
|
+
required: true,
|
|
9
|
+
description: "Visible legend that names the group."
|
|
10
|
+
},
|
|
11
|
+
description: {
|
|
12
|
+
type: "node",
|
|
13
|
+
description: "Supporting content associated with the fieldset."
|
|
14
|
+
},
|
|
15
|
+
disabled: {
|
|
16
|
+
type: "boolean",
|
|
17
|
+
default: false,
|
|
18
|
+
description: "Uses native fieldset disabling for descendant form controls."
|
|
19
|
+
},
|
|
20
|
+
className: { type: "string" }
|
|
21
|
+
},
|
|
22
|
+
slots: { children: { type: "ReactNode", required: true } },
|
|
23
|
+
composable_with: ["Field", "Input", "Checkbox", "FormErrorSummary"],
|
|
24
|
+
never_inside: ["Button"],
|
|
25
|
+
example: '<FormSection legend="Equipment details" description="Use the registered name.">\n <Field controlId="resource-name" label="Name"><Input /></Field>\n</FormSection>'
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
export {
|
|
29
|
+
FormSectionManifest
|
|
30
|
+
};
|