@oprt/react 0.0.0-stage → 0.1.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 +110 -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 +122 -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 +17811 -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,143 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/RadioGroup/RadioGroup.tsx
|
|
4
|
+
import { RadioGroup as AriaRadioGroup, Radio as AriaRadio } from "react-aria-components";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { createContext, forwardRef, useContext } from "react";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { Check } from "@oprt/icons";
|
|
9
|
+
import { useFieldWiring } from "../_internal/fieldIds.js";
|
|
10
|
+
import { RadioGroupManifest } from "./RadioGroup.manifest.js";
|
|
11
|
+
import { devValidate } from "../_internal/devValidate.js";
|
|
12
|
+
import { definedOnly, useAriaInvalidRef } from "../_internal/aria.js";
|
|
13
|
+
import { keyForIds } from "../_internal/hydration.js";
|
|
14
|
+
import { useMergedRefs, useInputRefObject } from "../_internal/mergeRefs.js";
|
|
15
|
+
import { FORCED_RADIO } from "../_internal/controlStyles.js";
|
|
16
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
+
var SizeContext = createContext("md");
|
|
18
|
+
var groupStyles = cva("flex font-sans", {
|
|
19
|
+
variants: {
|
|
20
|
+
orientation: {
|
|
21
|
+
vertical: "flex-col gap-2u",
|
|
22
|
+
// A row that does not fit wraps onto more rows (design call DC-8); arrow keys follow the
|
|
23
|
+
// reading order (RadioGroup-B2M-1).
|
|
24
|
+
horizontal: "flex-row flex-wrap gap-x-3u gap-y-2u"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: { orientation: "vertical" }
|
|
28
|
+
});
|
|
29
|
+
var radioWrapperStyles = "inline-flex items-center min-h-3u min-w-3u gap-2u text-oprt-base font-medium text-oprt-text font-sans cursor-pointer data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed data-[focus-visible]:[&_.oprt-radio-box]:border-oprt-border-focus data-[focus-visible]:[&_.oprt-radio-box]:shadow-oprt-focus data-[selected]:[&_.oprt-radio-box]:border-oprt-accent [&&]:data-[invalid]:[&_.oprt-radio-box]:border-oprt-error data-[selected]:[&_.oprt-radio-inner]:block";
|
|
30
|
+
var radioBoxStyles = cva(
|
|
31
|
+
"oprt-radio-box inline-flex shrink-0 items-center justify-center border bg-oprt-surface-2 transition-colors duration-oprt-fast border-oprt-border-control",
|
|
32
|
+
{
|
|
33
|
+
variants: {
|
|
34
|
+
size: {
|
|
35
|
+
sm: "h-2u w-2u",
|
|
36
|
+
md: "h-2.5u w-2.5u",
|
|
37
|
+
lg: "h-3u w-3u"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: { size: "md" }
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
var RadioGroup = forwardRef(
|
|
44
|
+
({
|
|
45
|
+
className,
|
|
46
|
+
orientation,
|
|
47
|
+
size = "md",
|
|
48
|
+
id,
|
|
49
|
+
children,
|
|
50
|
+
value,
|
|
51
|
+
defaultValue,
|
|
52
|
+
onValueChange,
|
|
53
|
+
disabled,
|
|
54
|
+
required,
|
|
55
|
+
name,
|
|
56
|
+
"aria-label": ariaLabel,
|
|
57
|
+
"aria-labelledby": ariaLabelledBy,
|
|
58
|
+
"aria-describedby": ariaDescribedBy,
|
|
59
|
+
"aria-invalid": ariaInvalid
|
|
60
|
+
}, ref) => {
|
|
61
|
+
const {
|
|
62
|
+
id: finalId,
|
|
63
|
+
labelledBy,
|
|
64
|
+
describedBy,
|
|
65
|
+
invalid: isInvalid,
|
|
66
|
+
required: isRequired
|
|
67
|
+
} = useFieldWiring(
|
|
68
|
+
{
|
|
69
|
+
id,
|
|
70
|
+
"aria-label": ariaLabel,
|
|
71
|
+
"aria-labelledby": ariaLabelledBy,
|
|
72
|
+
"aria-describedby": ariaDescribedBy,
|
|
73
|
+
"aria-invalid": ariaInvalid,
|
|
74
|
+
required
|
|
75
|
+
},
|
|
76
|
+
{ label: "labelledby" }
|
|
77
|
+
);
|
|
78
|
+
if (process.env.NODE_ENV !== "production") {
|
|
79
|
+
devValidate("RadioGroup", RadioGroupManifest.RadioGroup.props, { orientation, size });
|
|
80
|
+
}
|
|
81
|
+
const groupRef = useAriaInvalidRef(ref, isInvalid);
|
|
82
|
+
const rootProps = {
|
|
83
|
+
isDisabled: disabled ?? false,
|
|
84
|
+
isRequired,
|
|
85
|
+
isInvalid,
|
|
86
|
+
orientation: orientation ?? "vertical",
|
|
87
|
+
...definedOnly({
|
|
88
|
+
id: finalId,
|
|
89
|
+
"aria-label": ariaLabel,
|
|
90
|
+
"aria-labelledby": labelledBy,
|
|
91
|
+
"aria-describedby": describedBy,
|
|
92
|
+
name
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
if (value !== void 0) rootProps["value"] = value;
|
|
96
|
+
if (defaultValue !== void 0) rootProps["defaultValue"] = defaultValue;
|
|
97
|
+
if (onValueChange) rootProps["onChange"] = onValueChange;
|
|
98
|
+
return /* @__PURE__ */ jsx(SizeContext.Provider, { value: size, children: /* @__PURE__ */ jsx(
|
|
99
|
+
AriaRadioGroup,
|
|
100
|
+
{
|
|
101
|
+
ref: groupRef,
|
|
102
|
+
...rootProps,
|
|
103
|
+
className: clsx(groupStyles({ orientation }), className),
|
|
104
|
+
children
|
|
105
|
+
},
|
|
106
|
+
keyForIds(finalId, labelledBy)
|
|
107
|
+
) });
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
RadioGroup.displayName = "RadioGroup";
|
|
111
|
+
var Radio = forwardRef(
|
|
112
|
+
({ className, children, value, disabled, id, "aria-label": ariaLabel }, ref) => {
|
|
113
|
+
const size = useContext(SizeContext);
|
|
114
|
+
const setNode = useMergedRefs(ref);
|
|
115
|
+
const inputRef = useInputRefObject(setNode);
|
|
116
|
+
const itemProps = definedOnly({ id, "aria-label": ariaLabel });
|
|
117
|
+
return /* @__PURE__ */ jsxs(
|
|
118
|
+
AriaRadio,
|
|
119
|
+
{
|
|
120
|
+
value,
|
|
121
|
+
isDisabled: disabled ?? false,
|
|
122
|
+
inputRef,
|
|
123
|
+
...itemProps,
|
|
124
|
+
className: clsx(radioWrapperStyles, FORCED_RADIO, className),
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ jsx("span", { className: radioBoxStyles({ size }), children: /* @__PURE__ */ jsx(
|
|
127
|
+
Check,
|
|
128
|
+
{
|
|
129
|
+
size: size === "sm" ? 12 : size === "lg" ? 20 : 16,
|
|
130
|
+
className: "oprt-radio-inner hidden shrink-0 text-oprt-accent"
|
|
131
|
+
}
|
|
132
|
+
) }),
|
|
133
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 oprt-wrap-anywhere normal-case", children })
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
Radio.displayName = "Radio";
|
|
140
|
+
export {
|
|
141
|
+
Radio,
|
|
142
|
+
RadioGroup
|
|
143
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/RadioGroup/RadioGroup.manifest.ts
|
|
2
|
+
var RadioGroupManifest = {
|
|
3
|
+
RadioGroup: {
|
|
4
|
+
description: "Group of mutually exclusive options. Square outline with the shared OPERATOR Check icon when selected.",
|
|
5
|
+
props: {
|
|
6
|
+
value: { type: "string" },
|
|
7
|
+
defaultValue: { type: "string" },
|
|
8
|
+
onValueChange: {
|
|
9
|
+
type: "function",
|
|
10
|
+
description: "(value: string) => void. Called when the operator chooses an option."
|
|
11
|
+
},
|
|
12
|
+
disabled: { type: "boolean", default: false },
|
|
13
|
+
required: { type: "boolean", default: false },
|
|
14
|
+
orientation: { type: "enum", values: ["horizontal", "vertical"], default: "vertical" },
|
|
15
|
+
size: { type: "enum", values: ["sm", "md", "lg"], default: "md" },
|
|
16
|
+
name: { type: "string" }
|
|
17
|
+
},
|
|
18
|
+
slots: {
|
|
19
|
+
children: { type: "Radio", required: true }
|
|
20
|
+
},
|
|
21
|
+
composable_with: ["Field"],
|
|
22
|
+
never_inside: ["Button", "Badge"],
|
|
23
|
+
example: '<Field label="CHANNEL">\n <RadioGroup defaultValue="alpha">\n <Radio value="alpha">ALPHA</Radio>\n <Radio value="bravo">BRAVO</Radio>\n </RadioGroup>\n</Field>'
|
|
24
|
+
},
|
|
25
|
+
Radio: {
|
|
26
|
+
description: "Single radio option. Must be a child of <RadioGroup>.",
|
|
27
|
+
props: {
|
|
28
|
+
value: { type: "string", required: true },
|
|
29
|
+
disabled: { type: "boolean", default: false }
|
|
30
|
+
},
|
|
31
|
+
composable_with: ["RadioGroup"],
|
|
32
|
+
never_inside: ["Button", "Badge"],
|
|
33
|
+
example: '<Radio value="alpha">ALPHA</Radio>'
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var RadioGroupCompositionRules = {
|
|
37
|
+
RadioGroup: {
|
|
38
|
+
allowed_children: ["Radio"]
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
RadioGroupCompositionRules,
|
|
43
|
+
RadioGroupManifest
|
|
44
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/RadioGroup/index.ts
|
|
2
|
+
import { RadioGroup, Radio } from "./RadioGroup.js";
|
|
3
|
+
import { RadioGroupManifest, RadioGroupCompositionRules } from "./RadioGroup.manifest.js";
|
|
4
|
+
export {
|
|
5
|
+
Radio,
|
|
6
|
+
RadioGroup,
|
|
7
|
+
RadioGroupCompositionRules,
|
|
8
|
+
RadioGroupManifest
|
|
9
|
+
};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/Select/Select.tsx
|
|
4
|
+
import {
|
|
5
|
+
Select as AriaSelect,
|
|
6
|
+
SelectValue,
|
|
7
|
+
Button as AriaButton,
|
|
8
|
+
ListBox,
|
|
9
|
+
ListBoxItem
|
|
10
|
+
} from "react-aria-components";
|
|
11
|
+
import { cva } from "class-variance-authority";
|
|
12
|
+
import { forwardRef } from "react";
|
|
13
|
+
import clsx from "clsx";
|
|
14
|
+
import { joinIds, useFieldWiring, usePartIds } from "../_internal/fieldIds.js";
|
|
15
|
+
import { Check, ChevronDown } from "@oprt/icons";
|
|
16
|
+
import { SelectManifest } from "./Select.manifest.js";
|
|
17
|
+
import { devValidate } from "../_internal/devValidate.js";
|
|
18
|
+
import { definedOnly, renderInvalidButton, useAriaInvalidRef } from "../_internal/aria.js";
|
|
19
|
+
import { useHydrationRoot } from "../_internal/hydration.js";
|
|
20
|
+
import { MotionContext, useMotion } from "../_internal/motion.js";
|
|
21
|
+
import { MotionPopover } from "../_internal/MotionPopover.js";
|
|
22
|
+
import { MENU_ITEM_TEXT, SCREEN_MARGIN } from "../_internal/overlay.js";
|
|
23
|
+
import {
|
|
24
|
+
FORCED_FOCUS_OUTLINE,
|
|
25
|
+
FORCED_NO_RESTING_OUTLINE,
|
|
26
|
+
LISTBOX_EMPTY,
|
|
27
|
+
LISTBOX_ROW,
|
|
28
|
+
LISTBOX_SURFACE
|
|
29
|
+
} from "../_internal/controlStyles.js";
|
|
30
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
31
|
+
var triggerStyles = cva(
|
|
32
|
+
// A value or placeholder that does not fit wraps and the trigger grows taller, as Button does
|
|
33
|
+
// (the DC-8 ruling): the height is a minimum, and the vertical padding is what is left of it
|
|
34
|
+
// around one line and the 2 px of border, so a one-line trigger keeps exactly its token height.
|
|
35
|
+
"group/select inline-flex max-w-full items-center justify-between gap-1u border bg-oprt-surface-2 transition-colors duration-oprt-fast data-[focus-visible]:shadow-oprt-focus disabled:cursor-not-allowed disabled:bg-oprt-surface-3 disabled:border-oprt-border-control disabled:text-oprt-text-dim font-sans font-medium normal-case text-oprt-text outline-hidden",
|
|
36
|
+
{
|
|
37
|
+
variants: {
|
|
38
|
+
invalid: {
|
|
39
|
+
true: "border-oprt-error data-[focus-visible]:border-oprt-error",
|
|
40
|
+
// The control outline (design call DC-3); focus in the focus token, as the siblings do.
|
|
41
|
+
false: "border-oprt-border-control data-[focus-visible]:border-oprt-border-focus"
|
|
42
|
+
},
|
|
43
|
+
size: {
|
|
44
|
+
sm: "min-h-oprt-sm px-2u py-[calc((var(--oprt-height-sm)-2px-var(--oprt-line-base))/2)] text-oprt-base",
|
|
45
|
+
md: "min-h-oprt-md px-2u py-[calc((var(--oprt-height-md)-2px-var(--oprt-line-md))/2)] text-oprt-md",
|
|
46
|
+
lg: "min-h-oprt-lg px-3u py-[calc((var(--oprt-height-lg)-2px-var(--oprt-line-md))/2)] text-oprt-md"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: { invalid: false, size: "md" }
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
var contentStyles = LISTBOX_SURFACE;
|
|
53
|
+
var itemStyles = LISTBOX_ROW;
|
|
54
|
+
var Select = forwardRef(
|
|
55
|
+
({
|
|
56
|
+
motion = "auto",
|
|
57
|
+
placeholder,
|
|
58
|
+
emptyMessage = "No options available.",
|
|
59
|
+
className,
|
|
60
|
+
size,
|
|
61
|
+
invalid,
|
|
62
|
+
children,
|
|
63
|
+
id,
|
|
64
|
+
"aria-label": ariaLabel,
|
|
65
|
+
"aria-labelledby": ariaLabelledBy,
|
|
66
|
+
"aria-describedby": ariaDescribedBy,
|
|
67
|
+
value,
|
|
68
|
+
defaultValue,
|
|
69
|
+
onValueChange,
|
|
70
|
+
open,
|
|
71
|
+
defaultOpen,
|
|
72
|
+
onOpenChange,
|
|
73
|
+
disabled,
|
|
74
|
+
required,
|
|
75
|
+
name
|
|
76
|
+
}, ref) => {
|
|
77
|
+
const motionState = useMotion(motion);
|
|
78
|
+
const {
|
|
79
|
+
id: finalId,
|
|
80
|
+
labelledBy,
|
|
81
|
+
describedBy,
|
|
82
|
+
invalid: isInvalid,
|
|
83
|
+
required: isRequired,
|
|
84
|
+
field
|
|
85
|
+
} = useFieldWiring(
|
|
86
|
+
{
|
|
87
|
+
id,
|
|
88
|
+
"aria-label": ariaLabel,
|
|
89
|
+
"aria-labelledby": ariaLabelledBy,
|
|
90
|
+
"aria-describedby": ariaDescribedBy,
|
|
91
|
+
invalid,
|
|
92
|
+
required
|
|
93
|
+
},
|
|
94
|
+
{ label: "labelledby" }
|
|
95
|
+
);
|
|
96
|
+
const hydration = useHydrationRoot(finalId, labelledBy);
|
|
97
|
+
if (process.env.NODE_ENV !== "production") {
|
|
98
|
+
devValidate("Select", SelectManifest.Select.props, { size });
|
|
99
|
+
}
|
|
100
|
+
const rootProps = {
|
|
101
|
+
isDisabled: disabled ?? false,
|
|
102
|
+
isRequired,
|
|
103
|
+
isInvalid,
|
|
104
|
+
placeholder,
|
|
105
|
+
// An empty Select opens a list that says so (Select-R3), as an empty menu does (DC-6).
|
|
106
|
+
allowsEmptyCollection: true,
|
|
107
|
+
...definedOnly({
|
|
108
|
+
"aria-label": ariaLabel,
|
|
109
|
+
"aria-labelledby": labelledBy
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
if (value !== void 0) rootProps["selectedKey"] = value;
|
|
113
|
+
if (defaultValue !== void 0) rootProps["defaultSelectedKey"] = defaultValue;
|
|
114
|
+
if (onValueChange) rootProps["onSelectionChange"] = (k) => onValueChange(String(k));
|
|
115
|
+
if (open !== void 0) rootProps["isOpen"] = open;
|
|
116
|
+
if (defaultOpen !== void 0) rootProps["defaultOpen"] = defaultOpen;
|
|
117
|
+
if (onOpenChange) rootProps["onOpenChange"] = onOpenChange;
|
|
118
|
+
if (name !== void 0) rootProps["name"] = name;
|
|
119
|
+
const requiredId = usePartIds(["required"], { id: finalId }).required;
|
|
120
|
+
const triggerProps = definedOnly({
|
|
121
|
+
id: finalId,
|
|
122
|
+
"aria-label": ariaLabel,
|
|
123
|
+
"aria-describedby": joinIds(isRequired && requiredId, describedBy)
|
|
124
|
+
});
|
|
125
|
+
const triggerRef = useAriaInvalidRef(ref, isInvalid);
|
|
126
|
+
return /* @__PURE__ */ jsx(MotionContext.Provider, { value: motionState.mode, children: /* @__PURE__ */ jsxs(
|
|
127
|
+
AriaSelect,
|
|
128
|
+
{
|
|
129
|
+
...hydration.probeProps,
|
|
130
|
+
...rootProps,
|
|
131
|
+
className: "oprt-motion",
|
|
132
|
+
render: (domProps) => /* @__PURE__ */ jsx("div", { ...domProps, ...motionState.props }),
|
|
133
|
+
children: [
|
|
134
|
+
isRequired && /* @__PURE__ */ jsx("span", { id: requiredId, className: "sr-only", children: "Required" }),
|
|
135
|
+
/* @__PURE__ */ jsxs(
|
|
136
|
+
AriaButton,
|
|
137
|
+
{
|
|
138
|
+
ref: triggerRef,
|
|
139
|
+
render: renderInvalidButton(isInvalid),
|
|
140
|
+
...triggerProps,
|
|
141
|
+
className: clsx(
|
|
142
|
+
triggerStyles({ size, invalid: isInvalid }),
|
|
143
|
+
FORCED_NO_RESTING_OUTLINE,
|
|
144
|
+
FORCED_FOCUS_OUTLINE,
|
|
145
|
+
// Inside a Field the trigger fills its width like the other text controls; outside,
|
|
146
|
+
// it keeps its content width (ruling on DC-B04-4, Select-R5). `:where` gives the rule
|
|
147
|
+
// no specificity, so a width class on the Select still wins.
|
|
148
|
+
field && "[:where(&)]:w-full",
|
|
149
|
+
className
|
|
150
|
+
),
|
|
151
|
+
children: [
|
|
152
|
+
/* @__PURE__ */ jsx(SelectValue, { className: "min-w-0 oprt-wrap-anywhere text-left data-[placeholder]:text-oprt-text-placeholder group-disabled/select:data-[placeholder]:text-oprt-text-dim" }),
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
ChevronDown,
|
|
155
|
+
{
|
|
156
|
+
size: 12,
|
|
157
|
+
className: "oprt-motion-popover-chevron shrink-0",
|
|
158
|
+
"aria-hidden": "true"
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ jsx(
|
|
165
|
+
MotionPopover,
|
|
166
|
+
{
|
|
167
|
+
motionState,
|
|
168
|
+
className: contentStyles,
|
|
169
|
+
offset: 2,
|
|
170
|
+
containerPadding: SCREEN_MARGIN,
|
|
171
|
+
children: /* @__PURE__ */ jsx(
|
|
172
|
+
ListBox,
|
|
173
|
+
{
|
|
174
|
+
className: "outline-hidden",
|
|
175
|
+
renderEmptyState: () => /* @__PURE__ */ jsx("p", { className: LISTBOX_EMPTY, children: emptyMessage }),
|
|
176
|
+
children
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
hydration.key
|
|
184
|
+
) });
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
Select.displayName = "Select";
|
|
188
|
+
var SelectOption = forwardRef(
|
|
189
|
+
({ className, children, value, disabled, ...props }, ref) => {
|
|
190
|
+
const itemProps = {};
|
|
191
|
+
if (typeof children === "string") itemProps["textValue"] = children;
|
|
192
|
+
return /* @__PURE__ */ jsx(
|
|
193
|
+
ListBoxItem,
|
|
194
|
+
{
|
|
195
|
+
ref,
|
|
196
|
+
id: value,
|
|
197
|
+
isDisabled: disabled ?? false,
|
|
198
|
+
onKeyDown: (event) => {
|
|
199
|
+
if (event.key === "Enter" && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) {
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
}
|
|
202
|
+
event.continuePropagation();
|
|
203
|
+
},
|
|
204
|
+
className: clsx(itemStyles, className),
|
|
205
|
+
...itemProps,
|
|
206
|
+
...props,
|
|
207
|
+
children: ({ isSelected }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
208
|
+
/* @__PURE__ */ jsx("span", { className: MENU_ITEM_TEXT, children }),
|
|
209
|
+
isSelected && /* @__PURE__ */ jsx(Check, { size: 12, className: "shrink-0" })
|
|
210
|
+
] })
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
SelectOption.displayName = "SelectOption";
|
|
216
|
+
export {
|
|
217
|
+
Select,
|
|
218
|
+
SelectOption
|
|
219
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/Select/Select.manifest.ts
|
|
2
|
+
var SelectManifest = {
|
|
3
|
+
Select: {
|
|
4
|
+
description: "Single-select dropdown. Trigger matches Input geometry for one line and grows when its text wraps; inside a Field it fills the Field's width. Portal'd list with an accent border and the shared OPERATOR Check icon on the selected option; an empty Select opens a list that says so.",
|
|
5
|
+
props: {
|
|
6
|
+
motion: {
|
|
7
|
+
type: "enum",
|
|
8
|
+
values: ["auto", "none"],
|
|
9
|
+
default: "auto",
|
|
10
|
+
description: "Tactile pointer arrival, exit, and open-state chevron rotation; keyboard, assistive activation, and system reduced motion remain immediate."
|
|
11
|
+
},
|
|
12
|
+
value: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Controlled selected option value. Keep the selected option among the children; a value with no matching option shows the placeholder and submits nothing."
|
|
15
|
+
},
|
|
16
|
+
defaultValue: { type: "string", description: "Initial selected option value." },
|
|
17
|
+
onValueChange: {
|
|
18
|
+
type: "function",
|
|
19
|
+
description: "(value: string) => void. Called when the operator chooses an option."
|
|
20
|
+
},
|
|
21
|
+
open: { type: "boolean", description: "Controlled open state of the list." },
|
|
22
|
+
defaultOpen: { type: "boolean", default: false, description: "Initial open state." },
|
|
23
|
+
onOpenChange: {
|
|
24
|
+
type: "function",
|
|
25
|
+
description: "(open: boolean) => void. Called when the list opens or closes."
|
|
26
|
+
},
|
|
27
|
+
placeholder: { type: "string" },
|
|
28
|
+
emptyMessage: {
|
|
29
|
+
type: "string",
|
|
30
|
+
default: "No options available.",
|
|
31
|
+
description: "What the list says when there are no options to choose from."
|
|
32
|
+
},
|
|
33
|
+
"aria-label": {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Accessible name when there is no surrounding Field or visible heading."
|
|
36
|
+
},
|
|
37
|
+
"aria-labelledby": {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "IDs of visible elements that name the Select; wins over a Field's label."
|
|
40
|
+
},
|
|
41
|
+
"aria-describedby": {
|
|
42
|
+
type: "string",
|
|
43
|
+
description: "Description IDs; replaces a surrounding Field's help or error."
|
|
44
|
+
},
|
|
45
|
+
disabled: { type: "boolean", default: false },
|
|
46
|
+
required: { type: "boolean", default: false },
|
|
47
|
+
name: { type: "string" },
|
|
48
|
+
size: { type: "enum", values: ["sm", "md", "lg"], default: "md" },
|
|
49
|
+
invalid: { type: "boolean", default: false }
|
|
50
|
+
},
|
|
51
|
+
slots: {
|
|
52
|
+
children: { type: "SelectOption", required: true }
|
|
53
|
+
},
|
|
54
|
+
composable_with: ["Field"],
|
|
55
|
+
never_inside: ["Button", "Badge"],
|
|
56
|
+
example: '<Field label="THEATER">\n <Select placeholder="CHOOSE...">\n <SelectOption value="indo-pacific">INDO-PACIFIC</SelectOption>\n <SelectOption value="european">EUROPEAN</SelectOption>\n </Select>\n</Field>'
|
|
57
|
+
},
|
|
58
|
+
SelectOption: {
|
|
59
|
+
description: "Single option inside a Select. Must be a child of <Select>.",
|
|
60
|
+
props: {
|
|
61
|
+
value: { type: "string", required: true },
|
|
62
|
+
disabled: { type: "boolean", default: false }
|
|
63
|
+
},
|
|
64
|
+
composable_with: ["Select"],
|
|
65
|
+
never_inside: ["Button", "Badge"],
|
|
66
|
+
example: '<SelectOption value="alpha">ALPHA</SelectOption>'
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var SelectCompositionRules = {
|
|
70
|
+
Select: {
|
|
71
|
+
allowed_children: ["SelectOption"]
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export {
|
|
75
|
+
SelectCompositionRules,
|
|
76
|
+
SelectManifest
|
|
77
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/Sidebar/Sidebar.tsx
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
5
|
+
import {
|
|
6
|
+
Children,
|
|
7
|
+
forwardRef,
|
|
8
|
+
isValidElement,
|
|
9
|
+
useId
|
|
10
|
+
} from "react";
|
|
11
|
+
import clsx from "clsx";
|
|
12
|
+
import { useInsideNavigationLandmark } from "../_internal/navigationLandmark.js";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
var Sidebar = forwardRef(
|
|
15
|
+
({ className, children, ...props }, ref) => {
|
|
16
|
+
const insideLandmark = useInsideNavigationLandmark();
|
|
17
|
+
const Root = insideLandmark ? "div" : "nav";
|
|
18
|
+
const parts = Children.toArray(children);
|
|
19
|
+
let start = 0;
|
|
20
|
+
while (start < parts.length && isPart(parts[start], SidebarLogo)) start += 1;
|
|
21
|
+
let end = parts.length;
|
|
22
|
+
while (end > start && isPart(parts[end - 1], SidebarFooter)) end -= 1;
|
|
23
|
+
const list = parts.slice(start, end);
|
|
24
|
+
return /* @__PURE__ */ jsxs(
|
|
25
|
+
Root,
|
|
26
|
+
{
|
|
27
|
+
ref,
|
|
28
|
+
"aria-label": insideLandmark ? void 0 : "Sidebar",
|
|
29
|
+
className: clsx(
|
|
30
|
+
"flex flex-col w-60 max-w-full h-full bg-oprt-surface-1 border-r border-oprt-border font-sans",
|
|
31
|
+
className
|
|
32
|
+
),
|
|
33
|
+
...props,
|
|
34
|
+
children: [
|
|
35
|
+
parts.slice(0, start),
|
|
36
|
+
list.length > 0 && // 1 px of inline padding keeps the items' focus rings inside the scrolling box.
|
|
37
|
+
/* @__PURE__ */ jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
"data-oprt-sidebar-list": "",
|
|
41
|
+
className: "flex min-h-0 flex-1 flex-col overflow-y-auto px-px",
|
|
42
|
+
children: list
|
|
43
|
+
}
|
|
44
|
+
),
|
|
45
|
+
parts.slice(end)
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
Sidebar.displayName = "Sidebar";
|
|
52
|
+
function isPart(node, part) {
|
|
53
|
+
return isValidElement(node) && node.type === part;
|
|
54
|
+
}
|
|
55
|
+
var SidebarLogo = forwardRef(
|
|
56
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
57
|
+
"div",
|
|
58
|
+
{
|
|
59
|
+
ref,
|
|
60
|
+
className: clsx(
|
|
61
|
+
// A long name wraps and the row grows (the DC-8 rule): the height is a minimum, and the
|
|
62
|
+
// padding is what is left of it around one line and the 1 px border, so a one-line logo is
|
|
63
|
+
// exactly 40 px.
|
|
64
|
+
"flex shrink-0 items-center px-3u min-h-oprt-lg py-[calc((var(--oprt-height-lg)-1px-var(--oprt-line-lg))/2)] border-b border-oprt-border text-oprt-lg uppercase tracking-oprt-lg text-oprt-text oprt-wrap-anywhere [&_code]:normal-case [&_code]:tracking-normal [&_kbd]:normal-case [&_kbd]:tracking-normal",
|
|
65
|
+
className
|
|
66
|
+
),
|
|
67
|
+
...props
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
SidebarLogo.displayName = "SidebarLogo";
|
|
72
|
+
var SidebarSection = forwardRef(
|
|
73
|
+
({ className, label, children, ...props }, ref) => {
|
|
74
|
+
const labelId = useId();
|
|
75
|
+
return /* @__PURE__ */ jsxs(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
ref,
|
|
79
|
+
className: clsx("flex flex-col py-1u", className),
|
|
80
|
+
...label ? { role: "group", "aria-labelledby": labelId } : {},
|
|
81
|
+
...props,
|
|
82
|
+
children: [
|
|
83
|
+
label && /* @__PURE__ */ jsx(
|
|
84
|
+
"div",
|
|
85
|
+
{
|
|
86
|
+
id: labelId,
|
|
87
|
+
className: "m-0 px-3u py-1u text-oprt-sm uppercase tracking-oprt-sm text-oprt-text-dim oprt-wrap-anywhere",
|
|
88
|
+
children: label
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
children
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
SidebarSection.displayName = "SidebarSection";
|
|
98
|
+
var SidebarItem = forwardRef(
|
|
99
|
+
({ className, icon, active = false, href, asChild = false, children, ...props }, ref) => {
|
|
100
|
+
const Comp = asChild ? Slot : href ? "a" : "button";
|
|
101
|
+
const sharedProps = {
|
|
102
|
+
ref,
|
|
103
|
+
className: clsx(
|
|
104
|
+
// A long label wraps, a token breaks anywhere, and the row grows (the DC-8 rule): the
|
|
105
|
+
// height is a minimum and the padding is what is left of it around one line and the 2 px
|
|
106
|
+
// of border, so a one-line item is exactly 32 px.
|
|
107
|
+
"flex items-center gap-2u px-3u min-h-oprt-md py-[calc((var(--oprt-height-md)-2px-var(--oprt-line-base))/2)] text-left text-oprt-base font-medium uppercase tracking-oprt-caps oprt-wrap-anywhere [&_code]:normal-case [&_code]:tracking-normal [&_kbd]:normal-case [&_kbd]:tracking-normal text-oprt-text-dim hover:text-oprt-text hover:bg-oprt-surface-2 border border-transparent focus-visible:border-oprt-border-focus focus-visible:shadow-oprt-focus focus-visible:outline-hidden",
|
|
108
|
+
active && "text-oprt-accent bg-oprt-accent-ghost",
|
|
109
|
+
className
|
|
110
|
+
),
|
|
111
|
+
...props
|
|
112
|
+
};
|
|
113
|
+
if (active) sharedProps["aria-current"] = "page";
|
|
114
|
+
if (!asChild && href) sharedProps["href"] = href;
|
|
115
|
+
if (!asChild && !href) sharedProps["type"] = "button";
|
|
116
|
+
if (asChild) {
|
|
117
|
+
return /* @__PURE__ */ jsx(Comp, { ...sharedProps, children });
|
|
118
|
+
}
|
|
119
|
+
return /* @__PURE__ */ jsxs(Comp, { ...sharedProps, children: [
|
|
120
|
+
icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "inline-flex shrink-0 items-center", children: icon }),
|
|
121
|
+
children
|
|
122
|
+
] });
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
SidebarItem.displayName = "SidebarItem";
|
|
126
|
+
var SidebarFooter = forwardRef(
|
|
127
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
ref,
|
|
131
|
+
className: clsx(
|
|
132
|
+
"mt-auto shrink-0 min-w-0 break-words px-3u py-2u border-t border-oprt-border",
|
|
133
|
+
className
|
|
134
|
+
),
|
|
135
|
+
...props
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
SidebarFooter.displayName = "SidebarFooter";
|
|
140
|
+
export {
|
|
141
|
+
Sidebar,
|
|
142
|
+
SidebarFooter,
|
|
143
|
+
SidebarItem,
|
|
144
|
+
SidebarLogo,
|
|
145
|
+
SidebarSection
|
|
146
|
+
};
|