@rebasepro/ui 0.24.0 → 0.24.1-canary.gcb918fc
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/dist/components/Alert.d.ts +6 -0
- package/dist/components/Alert.es.js +82 -0
- package/dist/components/Alert.es.js.map +1 -0
- package/dist/components/Autocomplete.es.js +53 -0
- package/dist/components/Autocomplete.es.js.map +1 -0
- package/dist/components/Avatar.d.ts +3 -1
- package/dist/components/Avatar.es.js +37 -0
- package/dist/components/Avatar.es.js.map +1 -0
- package/dist/components/Badge.es.js +27 -0
- package/dist/components/Badge.es.js.map +1 -0
- package/dist/components/BooleanSwitch.es.js +75 -0
- package/dist/components/BooleanSwitch.es.js.map +1 -0
- package/dist/components/BooleanSwitchWithLabel.es.js +55 -0
- package/dist/components/BooleanSwitchWithLabel.es.js.map +1 -0
- package/dist/components/Button.es.js +58 -0
- package/dist/components/Button.es.js.map +1 -0
- package/dist/components/Card.es.js +26 -0
- package/dist/components/Card.es.js.map +1 -0
- package/dist/components/CenteredView.es.js +23 -0
- package/dist/components/CenteredView.es.js.map +1 -0
- package/dist/components/Checkbox.es.js +62 -0
- package/dist/components/Checkbox.es.js.map +1 -0
- package/dist/components/Chip.es.js +72 -0
- package/dist/components/Chip.es.js.map +1 -0
- package/dist/components/CircularProgress.es.js +28 -0
- package/dist/components/CircularProgress.es.js.map +1 -0
- package/dist/components/CircularProgressCenter.es.js +30 -0
- package/dist/components/CircularProgressCenter.es.js.map +1 -0
- package/dist/components/Collapse.es.js +57 -0
- package/dist/components/Collapse.es.js.map +1 -0
- package/dist/components/ColorPicker.es.js +89 -0
- package/dist/components/ColorPicker.es.js.map +1 -0
- package/dist/components/Container.es.js +31 -0
- package/dist/components/Container.es.js.map +1 -0
- package/dist/components/DateTimeField.d.ts +11 -1
- package/dist/components/DateTimeField.es.js +253 -0
- package/dist/components/DateTimeField.es.js.map +1 -0
- package/dist/components/DebouncedTextField.es.js +93 -0
- package/dist/components/DebouncedTextField.es.js.map +1 -0
- package/dist/components/Dialog.es.js +98 -0
- package/dist/components/Dialog.es.js.map +1 -0
- package/dist/components/DialogActions.es.js +15 -0
- package/dist/components/DialogActions.es.js.map +1 -0
- package/dist/components/DialogContent.es.js +18 -0
- package/dist/components/DialogContent.es.js.map +1 -0
- package/dist/components/DialogTitle.es.js +26 -0
- package/dist/components/DialogTitle.es.js.map +1 -0
- package/dist/components/ErrorBoundary.es.js +158 -0
- package/dist/components/ErrorBoundary.es.js.map +1 -0
- package/dist/components/ExpandablePanel.es.js +91 -0
- package/dist/components/ExpandablePanel.es.js.map +1 -0
- package/dist/components/FileUpload.es.js +58 -0
- package/dist/components/FileUpload.es.js.map +1 -0
- package/dist/components/FilterChip.es.js +31 -0
- package/dist/components/FilterChip.es.js.map +1 -0
- package/dist/components/IconButton.es.js +52 -0
- package/dist/components/IconButton.es.js.map +1 -0
- package/dist/components/InfoLabel.es.js +18 -0
- package/dist/components/InfoLabel.es.js.map +1 -0
- package/dist/components/InputLabel.es.js +27 -0
- package/dist/components/InputLabel.es.js.map +1 -0
- package/dist/components/Label.es.js +18 -0
- package/dist/components/Label.es.js.map +1 -0
- package/dist/components/LoadingButton.es.js +21 -0
- package/dist/components/LoadingButton.es.js.map +1 -0
- package/dist/components/Markdown.es.js +88 -0
- package/dist/components/Markdown.es.js.map +1 -0
- package/dist/components/Menu.es.js +46 -0
- package/dist/components/Menu.es.js.map +1 -0
- package/dist/components/Menubar.es.js +142 -0
- package/dist/components/Menubar.es.js.map +1 -0
- package/dist/components/MultiSelect.d.ts +1 -7
- package/dist/components/MultiSelect.es.js +271 -0
- package/dist/components/MultiSelect.es.js.map +1 -0
- package/dist/components/Paper.es.js +16 -0
- package/dist/components/Paper.es.js.map +1 -0
- package/dist/components/Popover.es.js +113 -0
- package/dist/components/Popover.es.js.map +1 -0
- package/dist/components/RadioGroup.es.js +30 -0
- package/dist/components/RadioGroup.es.js.map +1 -0
- package/dist/components/ResizablePanels.d.ts +3 -1
- package/dist/components/ResizablePanels.es.js +137 -0
- package/dist/components/ResizablePanels.es.js.map +1 -0
- package/dist/components/SearchBar.es.js +82 -0
- package/dist/components/SearchBar.es.js.map +1 -0
- package/dist/components/Select.d.ts +8 -1
- package/dist/components/Select.es.js +300 -0
- package/dist/components/Select.es.js.map +1 -0
- package/dist/components/Separator.es.js +20 -0
- package/dist/components/Separator.es.js.map +1 -0
- package/dist/components/Sheet.es.js +73 -0
- package/dist/components/Sheet.es.js.map +1 -0
- package/dist/components/Skeleton.es.js +33 -0
- package/dist/components/Skeleton.es.js.map +1 -0
- package/dist/components/Slider.es.js +56 -0
- package/dist/components/Slider.es.js.map +1 -0
- package/dist/components/Table.d.ts +18 -3
- package/dist/components/Table.es.js +69 -0
- package/dist/components/Table.es.js.map +1 -0
- package/dist/components/Tabs.es.js +101 -0
- package/dist/components/Tabs.es.js.map +1 -0
- package/dist/components/TextField.d.ts +0 -8
- package/dist/components/TextField.es.js +111 -0
- package/dist/components/TextField.es.js.map +1 -0
- package/dist/components/TextareaAutosize.es.js +187 -0
- package/dist/components/TextareaAutosize.es.js.map +1 -0
- package/dist/components/ToggleButtonGroup.d.ts +6 -1
- package/dist/components/ToggleButtonGroup.es.js +35 -0
- package/dist/components/ToggleButtonGroup.es.js.map +1 -0
- package/dist/components/Tooltip.d.ts +24 -0
- package/dist/components/Tooltip.es.js +165 -0
- package/dist/components/Tooltip.es.js.map +1 -0
- package/dist/components/Typography.es.js +85 -0
- package/dist/components/Typography.es.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTable.es.js +516 -0
- package/dist/components/VirtualTable/VirtualTable.es.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTableCell.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableCell.es.js +40 -0
- package/dist/components/VirtualTable/VirtualTableCell.es.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTableHeader.es.js +209 -0
- package/dist/components/VirtualTable/VirtualTableHeader.es.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js +166 -0
- package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -2
- package/dist/components/VirtualTable/VirtualTableRow.d.ts +6 -7
- package/dist/components/VirtualTable/VirtualTableRow.es.js +41 -0
- package/dist/components/VirtualTable/VirtualTableRow.es.js.map +1 -0
- package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +2 -1
- package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js +71 -0
- package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js.map +1 -0
- package/dist/components/VirtualTable/fields/VirtualTableInput.es.js +73 -0
- package/dist/components/VirtualTable/fields/VirtualTableInput.es.js.map +1 -0
- package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js +47 -0
- package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js.map +1 -0
- package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js +83 -0
- package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js.map +1 -0
- package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js +22 -0
- package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js.map +1 -0
- package/dist/components/VirtualTable/selection/SelectionContext.es.js +23 -0
- package/dist/components/VirtualTable/selection/SelectionContext.es.js.map +1 -0
- package/dist/components/VirtualTable/selection/SelectionStore.es.js +43 -0
- package/dist/components/VirtualTable/selection/SelectionStore.es.js.map +1 -0
- package/dist/components/VirtualTable/types.d.ts +1 -1
- package/dist/components/common/SelectInputLabel.es.js +28 -0
- package/dist/components/common/SelectInputLabel.es.js.map +1 -0
- package/dist/components/index.es.js +64 -0
- package/dist/hooks/PortalContainerContext.es.js +40 -0
- package/dist/hooks/PortalContainerContext.es.js.map +1 -0
- package/dist/hooks/UiLabelsContext.d.ts +63 -0
- package/dist/hooks/UiLabelsContext.es.js +59 -0
- package/dist/hooks/UiLabelsContext.es.js.map +1 -0
- package/dist/hooks/useDebounceCallback.es.js +15 -0
- package/dist/hooks/useDebounceCallback.es.js.map +1 -0
- package/dist/hooks/useDebounceValue.es.js +19 -0
- package/dist/hooks/useDebounceValue.es.js.map +1 -0
- package/dist/hooks/useDebouncedCallback.es.js +36 -0
- package/dist/hooks/useDebouncedCallback.es.js.map +1 -0
- package/dist/hooks/useInjectStyles.es.js +27 -0
- package/dist/hooks/useInjectStyles.es.js.map +1 -0
- package/dist/hooks/useIsDarkMode.es.js +61 -0
- package/dist/hooks/useIsDarkMode.es.js.map +1 -0
- package/dist/hooks/useModalFocus.es.js +81 -0
- package/dist/hooks/useModalFocus.es.js.map +1 -0
- package/dist/hooks/useOutsideAlerter.es.js +41 -0
- package/dist/hooks/useOutsideAlerter.es.js.map +1 -0
- package/dist/hooks/useRestoreInterruptedFocus.es.js +61 -0
- package/dist/hooks/useRestoreInterruptedFocus.es.js.map +1 -0
- package/dist/icons/GitHubIcon.es.js +23 -0
- package/dist/icons/GitHubIcon.es.js.map +1 -0
- package/dist/icons/HandleIcon.es.js +60 -0
- package/dist/icons/HandleIcon.es.js.map +1 -0
- package/dist/icons/Icon.es.js +25 -0
- package/dist/icons/Icon.es.js.map +1 -0
- package/dist/icons/LucideIconByName.d.ts +12 -9
- package/dist/icons/LucideIconByName.es.js +83 -0
- package/dist/icons/LucideIconByName.es.js.map +1 -0
- package/dist/icons/cool_icon_keys.es.js +55 -0
- package/dist/icons/cool_icon_keys.es.js.map +1 -0
- package/dist/icons/icon_keys.es.js +1941 -0
- package/dist/icons/icon_keys.es.js.map +1 -0
- package/dist/icons/index.d.ts +4 -3
- package/dist/icons/index.es.js +8 -0
- package/dist/icons/lucide_icon_map.d.ts +12 -0
- package/dist/icons/lucide_icon_map.es.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +87 -9563
- package/dist/styles.es.js +158 -0
- package/dist/styles.es.js.map +1 -0
- package/dist/util/chip_colors.es.js +290 -0
- package/dist/util/chip_colors.es.js.map +1 -0
- package/dist/util/cls.es.js +10 -0
- package/dist/util/cls.es.js.map +1 -0
- package/dist/util/debounce.es.js +22 -0
- package/dist/util/debounce.es.js.map +1 -0
- package/dist/util/hash.es.js +16 -0
- package/dist/util/hash.es.js.map +1 -0
- package/dist/util/keys.es.js +37 -0
- package/dist/util/keys.es.js.map +1 -0
- package/dist/util/lazy_chunk.es.js +96 -0
- package/dist/util/lazy_chunk.es.js.map +1 -0
- package/dist/views/CardView.d.ts +26 -2
- package/dist/views/CardView.es.js +435 -0
- package/dist/views/CardView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionCardView.es.js +179 -0
- package/dist/views/CollectionView/CollectionCardView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionKanbanView.es.js +172 -0
- package/dist/views/CollectionView/CollectionKanbanView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionListView.es.js +156 -0
- package/dist/views/CollectionView/CollectionListView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionTableView.es.js +149 -0
- package/dist/views/CollectionView/CollectionTableView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionView.es.js +197 -0
- package/dist/views/CollectionView/CollectionView.es.js.map +1 -0
- package/dist/views/CollectionView/CollectionViewToolbar.es.js +155 -0
- package/dist/views/CollectionView/CollectionViewToolbar.es.js.map +1 -0
- package/dist/views/CollectionView/DefaultCellRenderer.es.js +302 -0
- package/dist/views/CollectionView/DefaultCellRenderer.es.js.map +1 -0
- package/dist/views/CollectionView/resolveTitleProperty.es.js +56 -0
- package/dist/views/CollectionView/resolveTitleProperty.es.js.map +1 -0
- package/dist/views/CollectionView/utils.es.js +19 -0
- package/dist/views/CollectionView/utils.es.js.map +1 -0
- package/dist/views/Kanban/Board.es.js +237 -0
- package/dist/views/Kanban/Board.es.js.map +1 -0
- package/dist/views/Kanban/BoardColumn.es.js +81 -0
- package/dist/views/Kanban/BoardColumn.es.js.map +1 -0
- package/dist/views/Kanban/BoardColumnTitle.es.js +27 -0
- package/dist/views/Kanban/BoardColumnTitle.es.js.map +1 -0
- package/dist/views/Kanban/BoardSortableList.es.js +98 -0
- package/dist/views/Kanban/BoardSortableList.es.js.map +1 -0
- package/dist/views/Kanban/placement.es.js +27 -0
- package/dist/views/Kanban/placement.es.js.map +1 -0
- package/dist/views/KanbanView.es.js +11 -0
- package/dist/views/KanbanView.es.js.map +1 -0
- package/dist/views/ListView.d.ts +15 -2
- package/dist/views/ListView.es.js +245 -0
- package/dist/views/ListView.es.js.map +1 -0
- package/dist/views/useScrollParentRestoration.d.ts +8 -1
- package/dist/views/useScrollParentRestoration.es.js +75 -0
- package/dist/views/useScrollParentRestoration.es.js.map +1 -0
- package/package.json +2 -2
- package/dist/index.es.js.map +0 -1
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { defaultBorderMixin, focusedDisabled } from "../styles.es.js";
|
|
3
|
+
import { cls } from "../util/cls.es.js";
|
|
4
|
+
import { usePortalContainer } from "../hooks/PortalContainerContext.es.js";
|
|
5
|
+
import { iconSize } from "../icons/Icon.es.js";
|
|
6
|
+
import { SelectInputLabel } from "./common/SelectInputLabel.es.js";
|
|
7
|
+
import React, { Children, forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { CheckIcon, ChevronDownIcon } from "lucide-react";
|
|
10
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
11
|
+
//#region src/components/Select.tsx
|
|
12
|
+
/**
|
|
13
|
+
* Above this many options a closed select renders only the one it shows.
|
|
14
|
+
*
|
|
15
|
+
* Radix renders a closed select's items anyway — into a detached fragment, so
|
|
16
|
+
* that a letter typed on the focused trigger can pick one, and inside a form
|
|
17
|
+
* into the hidden native `<select>` as well. An enum field paid for its whole
|
|
18
|
+
* list on every render of the form around it: 500 options were 100 ms to mount
|
|
19
|
+
* and 17 ms per re-render in jsdom, linear in the count. Small lists keep
|
|
20
|
+
* Radix's own behaviour untouched; long ones answer typed letters here
|
|
21
|
+
* ({@link findNextOption}) and render their items when opened.
|
|
22
|
+
*/
|
|
23
|
+
var LAZY_OPTIONS_THRESHOLD = 50;
|
|
24
|
+
/** How long typed letters accumulate into one search — Radix's own window. */
|
|
25
|
+
var TYPEAHEAD_RESET_MS = 1e3;
|
|
26
|
+
/**
|
|
27
|
+
* The `SelectItem`s among `children`, in document order: through fragments,
|
|
28
|
+
* `SelectGroup`s and any other element wrapping them. An item rendered by a
|
|
29
|
+
* component of the caller's own is not seen, so such a list never counts as
|
|
30
|
+
* long and keeps the default behaviour.
|
|
31
|
+
*/
|
|
32
|
+
function collectOptions(children, into = []) {
|
|
33
|
+
Children.forEach(children, (child) => {
|
|
34
|
+
if (!React.isValidElement(child)) return;
|
|
35
|
+
if (child.type === SelectItem) {
|
|
36
|
+
const props = child.props;
|
|
37
|
+
into.push({
|
|
38
|
+
element: child,
|
|
39
|
+
value: String(props.value),
|
|
40
|
+
disabled: Boolean(props.disabled)
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const nested = child.props.children;
|
|
45
|
+
if (nested !== void 0) collectOptions(nested, into);
|
|
46
|
+
});
|
|
47
|
+
return into;
|
|
48
|
+
}
|
|
49
|
+
/** The text a node would render, as far as its elements' own children say. */
|
|
50
|
+
function textOf(node) {
|
|
51
|
+
if (node === null || node === void 0 || typeof node === "boolean") return "";
|
|
52
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
53
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
54
|
+
if (React.isValidElement(node)) return textOf(node.props.children);
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* What a typed letter matches an option against: its `textValue`, else the
|
|
59
|
+
* text of its children, else its value. Radix reads the rendered text, which
|
|
60
|
+
* an unrendered item does not have — an item whose label is drawn by a
|
|
61
|
+
* component (a chip) passes `textValue`.
|
|
62
|
+
*/
|
|
63
|
+
function optionLabel(option) {
|
|
64
|
+
const { textValue, children } = option.element.props;
|
|
65
|
+
if (textValue !== void 0) return textValue;
|
|
66
|
+
return textOf(children).trim() || option.value;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Radix's `findNextItem`, over options that are not rendered: the next option
|
|
70
|
+
* after the current one whose label starts with the search; the same letter
|
|
71
|
+
* typed again cycles through the options it starts.
|
|
72
|
+
*/
|
|
73
|
+
function findNextOption(options, search, current) {
|
|
74
|
+
if (options.length === 0) return void 0;
|
|
75
|
+
const normalizedSearch = (search.length > 1 && Array.from(search).every((char) => char === search[0]) ? search[0] : search).toLowerCase();
|
|
76
|
+
const start = Math.max(current ? options.indexOf(current) : -1, 0);
|
|
77
|
+
let wrapped = options.map((_, index) => options[(start + index) % options.length]);
|
|
78
|
+
if (normalizedSearch.length === 1) wrapped = wrapped.filter((option) => option !== current);
|
|
79
|
+
const next = wrapped.find((option) => optionLabel(option).toLowerCase().startsWith(normalizedSearch));
|
|
80
|
+
return next !== current ? next : void 0;
|
|
81
|
+
}
|
|
82
|
+
var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenChange, value, onChange, onValueChange, className, inputClassName, viewportClassName, placeholder, renderValue, label, size = "large", error, disabled, padding = true, position = "item-aligned", endAdornment, invisible, chevron = true, triggerContent, children, dataType = "string", portalContainer: manualContainer, "aria-label": ariaLabel, ...props }, ref) => {
|
|
83
|
+
const [openInternal, setOpenInternal] = useState(open ?? false);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
setOpenInternal(open ?? false);
|
|
86
|
+
}, [open]);
|
|
87
|
+
const contextContainer = usePortalContainer();
|
|
88
|
+
const finalContainer = manualContainer ?? contextContainer ?? void 0;
|
|
89
|
+
const onValueChangeInternal = useCallback((newValue) => {
|
|
90
|
+
let typedValue = newValue;
|
|
91
|
+
if (dataType === "boolean") {
|
|
92
|
+
if (newValue === "true") typedValue = true;
|
|
93
|
+
else if (newValue === "false") typedValue = false;
|
|
94
|
+
} else if (dataType === "number") {
|
|
95
|
+
if (!isNaN(Number(newValue)) && newValue.trim() !== "") typedValue = Number(newValue);
|
|
96
|
+
}
|
|
97
|
+
onValueChange?.(typedValue);
|
|
98
|
+
if (onChange) onChange({ target: {
|
|
99
|
+
name,
|
|
100
|
+
value: typedValue
|
|
101
|
+
} });
|
|
102
|
+
}, [
|
|
103
|
+
onChange,
|
|
104
|
+
onValueChange,
|
|
105
|
+
name,
|
|
106
|
+
dataType
|
|
107
|
+
]);
|
|
108
|
+
const hasValue = Array.isArray(value) ? value.length > 0 : value != null && value !== "" && value !== void 0;
|
|
109
|
+
const stringValue = value !== void 0 ? String(value) : void 0;
|
|
110
|
+
const options = useMemo(() => collectOptions(children), [children]);
|
|
111
|
+
const lazyOptions = options.length > LAZY_OPTIONS_THRESHOLD;
|
|
112
|
+
const renderedOptions = !lazyOptions || openInternal ? children : options.find((option) => option.value === stringValue)?.element ?? null;
|
|
113
|
+
const typeahead = useRef({ search: "" });
|
|
114
|
+
useEffect(() => () => clearTimeout(typeahead.current.timer), []);
|
|
115
|
+
const resetTypeahead = useCallback(() => {
|
|
116
|
+
clearTimeout(typeahead.current.timer);
|
|
117
|
+
typeahead.current.search = "";
|
|
118
|
+
}, []);
|
|
119
|
+
const onTriggerKeyDown = useCallback((event) => {
|
|
120
|
+
if (!lazyOptions || disabled) return;
|
|
121
|
+
if (event.ctrlKey || event.altKey || event.metaKey || event.key.length !== 1) return;
|
|
122
|
+
const state = typeahead.current;
|
|
123
|
+
if (event.key === " " && state.search === "") return;
|
|
124
|
+
const search = state.search + event.key;
|
|
125
|
+
state.search = search;
|
|
126
|
+
clearTimeout(state.timer);
|
|
127
|
+
state.timer = setTimeout(() => {
|
|
128
|
+
state.search = "";
|
|
129
|
+
}, TYPEAHEAD_RESET_MS);
|
|
130
|
+
const enabled = options.filter((option) => !option.disabled);
|
|
131
|
+
const next = findNextOption(enabled, search, enabled.find((option) => option.value === stringValue));
|
|
132
|
+
if (next) onValueChangeInternal(next.value);
|
|
133
|
+
}, [
|
|
134
|
+
lazyOptions,
|
|
135
|
+
disabled,
|
|
136
|
+
options,
|
|
137
|
+
stringValue,
|
|
138
|
+
onValueChangeInternal
|
|
139
|
+
]);
|
|
140
|
+
const hasEmptyOption = useMemo(() => options.some((option) => option.value === ""), [options]);
|
|
141
|
+
const onRootValueChange = useCallback((newValue) => {
|
|
142
|
+
if (lazyOptions && newValue === "" && !hasEmptyOption) return;
|
|
143
|
+
onValueChangeInternal(newValue);
|
|
144
|
+
}, [
|
|
145
|
+
lazyOptions,
|
|
146
|
+
hasEmptyOption,
|
|
147
|
+
onValueChangeInternal
|
|
148
|
+
]);
|
|
149
|
+
const displayChildren = useMemo(() => {
|
|
150
|
+
if (!hasValue || renderValue) return null;
|
|
151
|
+
let found = null;
|
|
152
|
+
Children.forEach(children, (child) => {
|
|
153
|
+
if (React.isValidElement(child) && String(child.props.value) === String(value)) found = child.props.children;
|
|
154
|
+
});
|
|
155
|
+
return found;
|
|
156
|
+
}, [
|
|
157
|
+
children,
|
|
158
|
+
hasValue,
|
|
159
|
+
renderValue,
|
|
160
|
+
value
|
|
161
|
+
]);
|
|
162
|
+
const emptyItemDisplay = useMemo(() => {
|
|
163
|
+
if (stringValue !== "") return null;
|
|
164
|
+
const emptyItem = Children.toArray(children).find((child) => React.isValidElement(child) && String(child.props.value) === "");
|
|
165
|
+
if (!emptyItem) return null;
|
|
166
|
+
return value !== void 0 && renderValue ? renderValue(value) : emptyItem.props.children;
|
|
167
|
+
}, [
|
|
168
|
+
children,
|
|
169
|
+
renderValue,
|
|
170
|
+
stringValue,
|
|
171
|
+
value
|
|
172
|
+
]);
|
|
173
|
+
const bare = triggerContent !== void 0;
|
|
174
|
+
const bareContent = bare ? /* @__PURE__ */ jsx("div", {
|
|
175
|
+
className: "flex w-full",
|
|
176
|
+
children: triggerContent
|
|
177
|
+
}) : void 0;
|
|
178
|
+
const controlHeight = {
|
|
179
|
+
"min-h-[28px]": size === "smallest",
|
|
180
|
+
"min-h-[32px]": size === "small",
|
|
181
|
+
"min-h-[40px]": size === "medium",
|
|
182
|
+
"min-h-[48px]": size === "large"
|
|
183
|
+
};
|
|
184
|
+
return /* @__PURE__ */ jsxs(SelectPrimitive.Root, {
|
|
185
|
+
name,
|
|
186
|
+
value: stringValue,
|
|
187
|
+
open: openInternal,
|
|
188
|
+
disabled,
|
|
189
|
+
onValueChange: onRootValueChange,
|
|
190
|
+
onOpenChange: (open) => {
|
|
191
|
+
if (open) resetTypeahead();
|
|
192
|
+
onOpenChange?.(open);
|
|
193
|
+
setOpenInternal(open);
|
|
194
|
+
},
|
|
195
|
+
...props,
|
|
196
|
+
children: [
|
|
197
|
+
typeof label === "string" ? /* @__PURE__ */ jsx(SelectInputLabel, {
|
|
198
|
+
error,
|
|
199
|
+
children: label
|
|
200
|
+
}) : label,
|
|
201
|
+
/* @__PURE__ */ jsxs("div", {
|
|
202
|
+
className: cls("select-none", !bare && "rounded-lg text-sm", !bare && (invisible ? "bg-transparent" : "bg-surface-field border border-hairline"), !bare && (disabled ? "bg-surface-field/60" : invisible ? "" : "transition-colors duration-150 hover:bg-surface-field-hover"), "relative flex items-center", className, !bare && controlHeight, {
|
|
203
|
+
"w-fit": !fullWidth,
|
|
204
|
+
"w-full": fullWidth
|
|
205
|
+
}),
|
|
206
|
+
children: [/* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
|
|
207
|
+
ref: inputRef,
|
|
208
|
+
id,
|
|
209
|
+
asChild: false,
|
|
210
|
+
type: "button",
|
|
211
|
+
onKeyDown: onTriggerKeyDown,
|
|
212
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? label : typeof renderValue === "string" ? renderValue : "Select an option"),
|
|
213
|
+
"aria-invalid": error || void 0,
|
|
214
|
+
className: cls("h-full", padding && !bare ? {
|
|
215
|
+
"px-4": size === "large",
|
|
216
|
+
"px-3": size === "medium",
|
|
217
|
+
"px-2": size === "small" || size === "smallest"
|
|
218
|
+
} : "", "outline-hidden focus:outline-hidden", "outline-none focus:outline-none", "select-none", !bare && [
|
|
219
|
+
"rounded-lg text-sm",
|
|
220
|
+
error ? "text-red-500 dark:text-red-600" : "focus:text-text-primary dark:focus:text-text-primary-dark",
|
|
221
|
+
error ? "border border-red-500 dark:border-red-600" : "",
|
|
222
|
+
disabled ? "text-surface-accent-600 dark:text-surface-accent-400" : "text-surface-accent-800 dark:text-white",
|
|
223
|
+
controlHeight
|
|
224
|
+
], "relative flex flex-row items-center", {
|
|
225
|
+
"w-full": fullWidth,
|
|
226
|
+
"w-fit": !fullWidth
|
|
227
|
+
}, inputClassName),
|
|
228
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
229
|
+
ref,
|
|
230
|
+
className: cls("flex-grow max-w-full flex flex-row gap-2 items-center", "overflow-visible", !bare && controlHeight),
|
|
231
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Value, {
|
|
232
|
+
onClick: (e) => {
|
|
233
|
+
e.preventDefault();
|
|
234
|
+
e.stopPropagation();
|
|
235
|
+
},
|
|
236
|
+
placeholder: bareContent ?? emptyItemDisplay ?? placeholder,
|
|
237
|
+
className: "w-full",
|
|
238
|
+
children: bareContent ?? (hasValue && value !== void 0 && renderValue ? renderValue(value) : displayChildren || placeholder)
|
|
239
|
+
})
|
|
240
|
+
}), chevron && !bare && /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
|
|
241
|
+
asChild: true,
|
|
242
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
243
|
+
size: size === "large" ? iconSize.medium : iconSize.small,
|
|
244
|
+
className: cls("transition", open ? "rotate-180" : "", {
|
|
245
|
+
"px-2": size === "large",
|
|
246
|
+
"px-1": size === "medium" || size === "small"
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
})]
|
|
250
|
+
}), endAdornment && /* @__PURE__ */ jsx("div", {
|
|
251
|
+
className: cls("h-full flex items-center absolute right-0 pr-12"),
|
|
252
|
+
onClick: (e) => {
|
|
253
|
+
e.preventDefault();
|
|
254
|
+
e.stopPropagation();
|
|
255
|
+
},
|
|
256
|
+
children: endAdornment
|
|
257
|
+
})]
|
|
258
|
+
}),
|
|
259
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Portal, {
|
|
260
|
+
container: finalContainer,
|
|
261
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Content, {
|
|
262
|
+
position,
|
|
263
|
+
className: cls(focusedDisabled, "z-50 relative overflow-hidden border bg-surface-card p-2 rounded-lg shadow-lg", defaultBorderMixin),
|
|
264
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, {
|
|
265
|
+
className: cls("p-1", viewportClassName),
|
|
266
|
+
style: { maxHeight: "var(--radix-select-content-available-height)" },
|
|
267
|
+
children: renderedOptions
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
]
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
Select.displayName = "Select";
|
|
275
|
+
var SelectItem = React.memo(function SelectItem({ value, children, disabled, className, textValue }) {
|
|
276
|
+
const stringValue = String(value);
|
|
277
|
+
return /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
|
|
278
|
+
value: stringValue,
|
|
279
|
+
disabled,
|
|
280
|
+
textValue,
|
|
281
|
+
className: cls("w-full", "relative flex items-center p-2 rounded-md text-sm text-surface-accent-700 dark:text-surface-accent-300", "focus:z-10", "data-[state=checked]:bg-surface-active focus:bg-surface-hover", "data-[state=checked]:focus:bg-surface-active", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer", "[&>*]:w-full", "overflow-visible", className),
|
|
282
|
+
children: [/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children }), /* @__PURE__ */ jsx("div", {
|
|
283
|
+
className: "absolute left-1 data-[state=checked]:block hidden",
|
|
284
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { size: iconSize.smallest })
|
|
285
|
+
})]
|
|
286
|
+
}, stringValue);
|
|
287
|
+
});
|
|
288
|
+
var SelectGroup = React.memo(function SelectGroup({ label, children, className }) {
|
|
289
|
+
return /* @__PURE__ */ jsxs(SelectPrimitive.Group, {
|
|
290
|
+
className: "mt-6 first:mt-2",
|
|
291
|
+
children: [/* @__PURE__ */ jsx(SelectPrimitive.Label, {
|
|
292
|
+
className: cls("text-xs text-surface-accent-900 dark:text-white uppercase tracking-wider font-semibold", "px-2 py-2", className),
|
|
293
|
+
children: label
|
|
294
|
+
}), children]
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
//#endregion
|
|
298
|
+
export { Select, SelectGroup, SelectItem };
|
|
299
|
+
|
|
300
|
+
//# sourceMappingURL=Select.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.es.js","names":[],"sources":["../../src/components/Select.tsx"],"sourcesContent":["\n\"use client\";\nimport { CheckIcon, ChevronDownIcon } from \"lucide-react\";\nimport { iconSize } from \"../icons/Icon\";\nimport React, { ChangeEvent, Children, forwardRef, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport {\n defaultBorderMixin,\n fieldBackgroundDisabledMixin,\n fieldBackgroundHoverMixin,\n fieldBackgroundInvisibleMixin,\n fieldBackgroundMixin,\n focusedDisabled\n} from \"../styles\";\n\nimport { cls } from \"../util\";\nimport { SelectInputLabel } from \"./common/SelectInputLabel\";\nimport { usePortalContainer } from \"../hooks/PortalContainerContext\";\n\nexport type SelectValue = string | number | boolean;\n\n/**\n * Above this many options a closed select renders only the one it shows.\n *\n * Radix renders a closed select's items anyway — into a detached fragment, so\n * that a letter typed on the focused trigger can pick one, and inside a form\n * into the hidden native `<select>` as well. An enum field paid for its whole\n * list on every render of the form around it: 500 options were 100 ms to mount\n * and 17 ms per re-render in jsdom, linear in the count. Small lists keep\n * Radix's own behaviour untouched; long ones answer typed letters here\n * ({@link findNextOption}) and render their items when opened.\n */\nconst LAZY_OPTIONS_THRESHOLD = 50;\n\n/** How long typed letters accumulate into one search — Radix's own window. */\nconst TYPEAHEAD_RESET_MS = 1000;\n\ntype SelectOption = {\n element: React.ReactElement<SelectItemProps<SelectValue>>,\n value: string,\n disabled: boolean\n};\n\n/**\n * The `SelectItem`s among `children`, in document order: through fragments,\n * `SelectGroup`s and any other element wrapping them. An item rendered by a\n * component of the caller's own is not seen, so such a list never counts as\n * long and keeps the default behaviour.\n */\nfunction collectOptions(children: React.ReactNode, into: SelectOption[] = []): SelectOption[] {\n Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n if (child.type === SelectItem) {\n const props = child.props as SelectItemProps<SelectValue>;\n into.push({\n element: child as React.ReactElement<SelectItemProps<SelectValue>>,\n value: String(props.value),\n disabled: Boolean(props.disabled)\n });\n return;\n }\n const nested = (child.props as { children?: React.ReactNode }).children;\n if (nested !== undefined) collectOptions(nested, into);\n });\n return into;\n}\n\n/** The text a node would render, as far as its elements' own children say. */\nfunction textOf(node: React.ReactNode): string {\n if (node === null || node === undefined || typeof node === \"boolean\") return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map(textOf).join(\"\");\n if (React.isValidElement(node)) return textOf((node.props as { children?: React.ReactNode }).children);\n return \"\";\n}\n\n/**\n * What a typed letter matches an option against: its `textValue`, else the\n * text of its children, else its value. Radix reads the rendered text, which\n * an unrendered item does not have — an item whose label is drawn by a\n * component (a chip) passes `textValue`.\n */\nfunction optionLabel(option: SelectOption): string {\n const { textValue, children } = option.element.props;\n if (textValue !== undefined) return textValue;\n return textOf(children).trim() || option.value;\n}\n\n/**\n * Radix's `findNextItem`, over options that are not rendered: the next option\n * after the current one whose label starts with the search; the same letter\n * typed again cycles through the options it starts.\n */\nfunction findNextOption(options: SelectOption[], search: string, current: SelectOption | undefined): SelectOption | undefined {\n if (options.length === 0) return undefined;\n const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);\n const normalizedSearch = (isRepeated ? search[0] : search).toLowerCase();\n const start = Math.max(current ? options.indexOf(current) : -1, 0);\n let wrapped = options.map((_, index) => options[(start + index) % options.length]);\n if (normalizedSearch.length === 1) wrapped = wrapped.filter((option) => option !== current);\n const next = wrapped.find((option) => optionLabel(option).toLowerCase().startsWith(normalizedSearch));\n return next !== current ? next : undefined;\n}\n\nexport type SelectProps<T extends SelectValue = string> = {\n open?: boolean,\n name?: string,\n fullWidth?: boolean,\n id?: string,\n onOpenChange?: (open: boolean) => void,\n value?: T,\n className?: string,\n inputClassName?: string,\n viewportClassName?: string,\n onChange?: React.EventHandler<ChangeEvent<HTMLSelectElement>>,\n onValueChange?: (updatedValue: T) => void,\n placeholder?: React.ReactNode,\n renderValue?: (value: T) => React.ReactNode,\n size?: \"smallest\" | \"small\" | \"medium\" | \"large\",\n label?: React.ReactNode | string,\n disabled?: boolean,\n error?: boolean,\n position?: \"item-aligned\" | \"popper\",\n endAdornment?: React.ReactNode,\n inputRef?: React.Ref<HTMLButtonElement>,\n padding?: boolean,\n invisible?: boolean,\n /**\n * Whether the trigger draws its own chevron. A table cell turns it off:\n * the cell draws one opener for every kind of editor, in the same place.\n */\n chevron?: boolean,\n /**\n * Replaces everything the trigger draws — the value, the box, its padding,\n * its height and the chevron — with this node. For a caller that frames\n * the select itself: a table cell passes the preview it shows at rest, so\n * selecting the cell moves nothing.\n */\n triggerContent?: React.ReactNode,\n children?: React.ReactNode;\n dataType?: \"string\" | \"number\" | \"boolean\";\n portalContainer?: HTMLElement | null; // Explicitly added to props type if missing\n /**\n * Accessible name for the trigger, for a select whose `label` is a node\n * rather than a string — or which shows no label at all.\n *\n * Without it such a select announces the literal fallback \"Select an\n * option\", which is indistinguishable from every other unlabelled select\n * on the screen.\n */\n \"aria-label\"?: string;\n};\n\nexport const Select = forwardRef<HTMLDivElement, SelectProps>(({\n inputRef,\n open,\n name,\n fullWidth = false,\n id,\n onOpenChange,\n value,\n onChange,\n onValueChange,\n className,\n inputClassName,\n viewportClassName,\n placeholder,\n renderValue,\n label,\n size = \"large\",\n error,\n disabled,\n padding = true,\n position = \"item-aligned\",\n endAdornment,\n invisible,\n chevron = true,\n triggerContent,\n children,\n dataType = \"string\",\n portalContainer: manualContainer, // Rename to avoid confusion\n \"aria-label\": ariaLabel,\n ...props\n}, ref) => {\n\n const [openInternal, setOpenInternal] = useState(open ?? false);\n\n useEffect(() => {\n setOpenInternal(open ?? false);\n }, [open]);\n\n // Get the portal container from context\n const contextContainer = usePortalContainer();\n\n // Resolve final container (Manual Prop > Context Container > Undefined/Body)\n const finalContainer = (manualContainer ?? contextContainer ?? undefined) as HTMLElement | undefined;\n\n const onValueChangeInternal = useCallback((newValue: string) => {\n let typedValue: SelectValue = newValue;\n if (dataType === \"boolean\") {\n if (newValue === \"true\") typedValue = true;\n else if (newValue === \"false\") typedValue = false;\n } else if (dataType === \"number\") {\n if (!isNaN(Number(newValue)) && newValue.trim() !== \"\") typedValue = Number(newValue);\n }\n\n onValueChange?.(typedValue as SelectValue & typeof value);\n if (onChange) {\n const event = {\n target: {\n name,\n value: typedValue\n }\n } as ChangeEvent<HTMLSelectElement>;\n onChange(event);\n }\n }, [onChange, onValueChange, name, dataType]);\n\n const hasValue = Array.isArray(value) ? value.length > 0 : (value != null && value !== \"\" && value !== undefined);\n const stringValue = value !== undefined ? String(value) : undefined;\n\n // A long list renders its items only while open; closed, it renders the\n // one it shows, which keeps that option in the native `<select>` a form\n // submits. See LAZY_OPTIONS_THRESHOLD.\n const options = useMemo(() => collectOptions(children), [children]);\n const lazyOptions = options.length > LAZY_OPTIONS_THRESHOLD;\n const renderedOptions = !lazyOptions || openInternal\n ? children\n : (options.find((option) => option.value === stringValue)?.element ?? null);\n\n // Type-ahead on the closed trigger of a long list, where Radix has no\n // rendered items to search. Radix's own handler still runs after this one\n // and finds nothing to change; it keeps its own buffer in step, so a space\n // typed mid-search does not open the list, as before.\n const typeahead = useRef<{ search: string, timer?: ReturnType<typeof setTimeout> }>({ search: \"\" });\n useEffect(() => () => clearTimeout(typeahead.current.timer), []);\n const resetTypeahead = useCallback(() => {\n clearTimeout(typeahead.current.timer);\n typeahead.current.search = \"\";\n }, []);\n const onTriggerKeyDown = useCallback((event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (!lazyOptions || disabled) return;\n if (event.ctrlKey || event.altKey || event.metaKey || event.key.length !== 1) return;\n const state = typeahead.current;\n // A space starts nothing: it opens the list.\n if (event.key === \" \" && state.search === \"\") return;\n const search = state.search + event.key;\n state.search = search;\n clearTimeout(state.timer);\n state.timer = setTimeout(() => {\n state.search = \"\";\n }, TYPEAHEAD_RESET_MS);\n const enabled = options.filter((option) => !option.disabled);\n const current = enabled.find((option) => option.value === stringValue);\n const next = findNextOption(enabled, search, current);\n if (next) onValueChangeInternal(next.value);\n }, [lazyOptions, disabled, options, stringValue, onValueChangeInternal]);\n\n // Inside a form Radix mirrors the value into a hidden native `<select>` and\n // reports whatever that select then holds. A closed long list has only its\n // shown option in there, so when the value moves to another option — typed,\n // or set by the form — the select has no match for one commit and reports\n // \"\", a change nobody made, which would clear the field. A real \"\" can only\n // come from an option whose value is \"\".\n const hasEmptyOption = useMemo(() => options.some((option) => option.value === \"\"), [options]);\n const onRootValueChange = useCallback((newValue: string) => {\n if (lazyOptions && newValue === \"\" && !hasEmptyOption) return;\n onValueChangeInternal(newValue);\n }, [lazyOptions, hasEmptyOption, onValueChangeInternal]);\n\n const displayChildren = useMemo(() => {\n if (!hasValue || renderValue) return null;\n\n // Find the child that matches the current value to display its content\n let found: React.ReactNode = null;\n Children.forEach(children, (child) => {\n if (React.isValidElement<SelectItemProps>(child) && String(child.props.value) === String(value)) {\n found = child.props.children;\n }\n });\n return found;\n }, [children, hasValue, renderValue, value]);\n\n // Radix reads a value of \"\" as nothing selected and shows the placeholder\n // slot, whatever the Value's children say. So an item whose value really is\n // \"\" (an \"inherit the default\" choice) is shown through that slot, or the\n // trigger stays blank while it is the selected one.\n const emptyItemDisplay = useMemo(() => {\n if (stringValue !== \"\") return null;\n const emptyItem = Children.toArray(children).find((child): child is React.ReactElement<SelectItemProps> =>\n React.isValidElement<SelectItemProps>(child) && String(child.props.value) === \"\");\n if (!emptyItem) return null;\n return value !== undefined && renderValue ? renderValue(value) : emptyItem.props.children;\n }, [children, renderValue, stringValue, value]);\n\n const bare = triggerContent !== undefined;\n // Radix's value slot is an inline `span` that drops the class it is\n // given, so a chip inside it sits on a text baseline and the slot stands\n // a pixel taller than the chip. A block of its own takes it off the line.\n const bareContent = bare ? <div className={\"flex w-full\"}>{triggerContent}</div> : undefined;\n\n const controlHeight = {\n \"min-h-[28px]\": size === \"smallest\",\n \"min-h-[32px]\": size === \"small\",\n \"min-h-[40px]\": size === \"medium\",\n \"min-h-[48px]\": size === \"large\"\n };\n\n return (\n <SelectPrimitive.Root\n name={name}\n value={stringValue}\n open={openInternal}\n disabled={disabled}\n onValueChange={onRootValueChange}\n onOpenChange={(open) => {\n if (open) resetTypeahead();\n onOpenChange?.(open);\n setOpenInternal(open);\n }}\n {...props}>\n {typeof label === \"string\" ? <SelectInputLabel error={error}>{label}</SelectInputLabel> : label}\n <div className={cls(\n \"select-none\",\n !bare && \"rounded-lg text-sm\",\n !bare && (invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin),\n // An invisible field has no hover fill of its own: whatever frames it (a table cell) carries the hover.\n !bare && (disabled ? fieldBackgroundDisabledMixin : (invisible ? \"\" : fieldBackgroundHoverMixin)),\n \"relative flex items-center\",\n className,\n !bare && controlHeight,\n {\n \"w-fit\": !fullWidth,\n \"w-full\": fullWidth\n }\n )}>\n <SelectPrimitive.Trigger\n ref={inputRef}\n id={id}\n asChild={false}\n type=\"button\"\n onKeyDown={onTriggerKeyDown}\n // A `label` that is an element — which every entity form\n // passes, because the label carries the property's type\n // icon — fell through to a hard-coded English literal, so\n // every enum field in every form announced itself as\n // \"Select an option\". Callers pass `aria-label` now; the\n // literal stays as the last resort, and is unreachable for\n // anything that names itself.\n aria-label={ariaLabel ?? (typeof label === \"string\" ? label : (typeof renderValue === \"string\" ? renderValue : \"Select an option\"))}\n aria-invalid={error || undefined}\n className={cls(\n \"h-full\",\n padding && !bare ? {\n \"px-4\": size === \"large\",\n \"px-3\": size === \"medium\",\n \"px-2\": size === \"small\" || size === \"smallest\"\n } : \"\",\n \"outline-hidden focus:outline-hidden\",\n \"outline-none focus:outline-none\",\n \"select-none\",\n !bare && [\n \"rounded-lg text-sm\",\n error ? \"text-red-500 dark:text-red-600\" : \"focus:text-text-primary dark:focus:text-text-primary-dark\",\n error ? \"border border-red-500 dark:border-red-600\" : \"\",\n disabled ? \"text-surface-accent-600 dark:text-surface-accent-400\" : \"text-surface-accent-800 dark:text-white\",\n controlHeight\n ],\n \"relative flex flex-row items-center\",\n {\n \"w-full\": fullWidth,\n \"w-fit\": !fullWidth\n },\n inputClassName\n )}\n >\n <div\n ref={ref}\n className={cls(\n \"flex-grow max-w-full flex flex-row gap-2 items-center\",\n \"overflow-visible\",\n !bare && controlHeight\n )}>\n <SelectPrimitive.Value\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n placeholder={bareContent ?? emptyItemDisplay ?? placeholder}\n className={\"w-full\"}>\n\n {bareContent ?? (hasValue && value !== undefined && renderValue\n ? renderValue(value)\n : (displayChildren || placeholder)\n )}\n\n </SelectPrimitive.Value>\n </div>\n\n {chevron && !bare && <SelectPrimitive.Icon asChild>\n <ChevronDownIcon size={size === \"large\" ? iconSize.medium : iconSize.small}\n className={cls(\"transition\", open ? \"rotate-180\" : \"\", {\n \"px-2\": size === \"large\",\n \"px-1\": size === \"medium\" || size === \"small\"\n })}/>\n </SelectPrimitive.Icon>}\n </SelectPrimitive.Trigger>\n\n {endAdornment && (\n <div\n className={cls(\"h-full flex items-center absolute right-0 pr-12\")}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}>\n {endAdornment}\n </div>\n )}\n </div>\n\n {/* Pass the calculated finalContainer */}\n <SelectPrimitive.Portal container={finalContainer}>\n <SelectPrimitive.Content position={position}\n className={cls(focusedDisabled, \"z-50 relative overflow-hidden border bg-surface-card p-2 rounded-lg shadow-lg\", defaultBorderMixin)}>\n <SelectPrimitive.Viewport className={cls(\"p-1\", viewportClassName)}\n style={{ maxHeight: \"var(--radix-select-content-available-height)\" }}>\n {renderedOptions}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n );\n});\n\nSelect.displayName = \"Select\";\n\nexport type SelectItemProps<T extends SelectValue = string> = {\n value: T,\n children?: React.ReactNode,\n disabled?: boolean,\n className?: string,\n /**\n * The text a letter typed on the focused select matches this option by.\n * Defaults to the option's text. Set it when the option is drawn by a\n * component (a chip, an icon with a name inside it): a closed select with\n * more than 50 options does not render them, so their text cannot be read.\n */\n textValue?: string,\n};\n\nexport const SelectItem = React.memo(function SelectItem<T extends SelectValue = string>({\n value,\n children,\n disabled,\n className,\n textValue\n}: SelectItemProps<T>) {\n // Convert value to string for Radix UI\n const stringValue = String(value);\n\n return <SelectPrimitive.Item\n key={stringValue}\n value={stringValue}\n disabled={disabled}\n textValue={textValue}\n className={cls(\n \"w-full\",\n \"relative flex items-center p-2 rounded-md text-sm text-surface-accent-700 dark:text-surface-accent-300\",\n \"focus:z-10\",\n \"data-[state=checked]:bg-surface-active focus:bg-surface-hover\",\n \"data-[state=checked]:focus:bg-surface-active\",\n disabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\",\n \"[&>*]:w-full\",\n \"overflow-visible\",\n className\n )}>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <div\n className=\"absolute left-1 data-[state=checked]:block hidden\">\n <CheckIcon size={iconSize.smallest}/>\n </div>\n </SelectPrimitive.Item>;\n});\n\nexport type SelectGroupProps = {\n label: React.ReactNode,\n children: React.ReactNode,\n className?: string\n};\n\nexport const SelectGroup = React.memo(function SelectGroup({\n label,\n children,\n className\n}: SelectGroupProps) {\n // The items go inside the group and the label is Radix's own, so the\n // `role=\"group\"` holds its options and is named by the label.\n return <SelectPrimitive.Group className=\"mt-6 first:mt-2\">\n <SelectPrimitive.Label\n className={cls(\n \"text-xs text-surface-accent-900 dark:text-white uppercase tracking-wider font-semibold\",\n \"px-2 py-2\",\n className\n )}>\n {label}\n </SelectPrimitive.Label>\n {children}\n </SelectPrimitive.Group>;\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cls } from "../util/cls.es.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
4
|
+
//#region src/components/Separator.tsx
|
|
5
|
+
function Separator({ orientation, decorative, className }) {
|
|
6
|
+
if (orientation === "horizontal") return /* @__PURE__ */ jsx(SeparatorPrimitive.Root, {
|
|
7
|
+
decorative,
|
|
8
|
+
orientation: "horizontal",
|
|
9
|
+
className: cls("bg-hairline data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-4", className)
|
|
10
|
+
});
|
|
11
|
+
else return /* @__PURE__ */ jsx(SeparatorPrimitive.Root, {
|
|
12
|
+
className: cls("bg-hairline data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px mx-4", className),
|
|
13
|
+
decorative,
|
|
14
|
+
orientation: "vertical"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { Separator };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=Separator.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Separator.es.js","names":[],"sources":["../../src/components/Separator.tsx"],"sourcesContent":["import * as SeparatorPrimitive from \"@radix-ui/react-separator\";\nimport { cls } from \"../util\";\n\nexport function Separator({\n orientation,\n decorative,\n className\n }: {\n orientation: \"horizontal\" | \"vertical\",\n decorative?: boolean,\n className?: string\n}) {\n if (orientation === \"horizontal\")\n return (\n <SeparatorPrimitive.Root\n decorative={decorative}\n orientation=\"horizontal\"\n className={cls(\"bg-hairline data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-4\", className)}/>\n );\n else\n return (\n <SeparatorPrimitive.Root\n className={cls(\"bg-hairline data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px mx-4\", className)}\n decorative={decorative}\n orientation=\"vertical\"\n />\n );\n}\n"],"mappings":";;;;AAGA,SAAgB,UAAU,EACI,aACA,YACA,aAK3B;CACC,IAAI,gBAAgB,cAChB,OACI,oBAAC,mBAAmB,MAApB;EACgB;EACZ,aAAY;EACZ,WAAW,IAAI,gKAAgK,SAAS;CAAG,CAAA;MAGnM,OACI,oBAAC,mBAAmB,MAApB;EACI,WAAW,IAAI,gKAAgK,SAAS;EAC5K;EACZ,aAAY;CACf,CAAA;AAEb"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { defaultBorderMixin } from "../styles.es.js";
|
|
3
|
+
import { cls } from "../util/cls.es.js";
|
|
4
|
+
import { PortalContainerProvider, usePortalContainer } from "../hooks/PortalContainerContext.es.js";
|
|
5
|
+
import { useRestoreInterruptedFocus } from "../hooks/useRestoreInterruptedFocus.es.js";
|
|
6
|
+
import { useModalFocus } from "../hooks/useModalFocus.es.js";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
10
|
+
//#region src/components/Sheet.tsx
|
|
11
|
+
var Sheet = ({ children, side = "right", title, modal = true, includeBackgroundOverlay = true, open, onOpenChange, onPointerDownOutside, onInteractOutside, initialFocus, onOpenAutoFocus, onCloseAutoFocus, transparent, className, style, overlayClassName, overlayZIndex = "z-50", overlayStyle, portalContainer, ...props }) => {
|
|
12
|
+
const [displayed, setDisplayed] = useState(false);
|
|
13
|
+
const [contentEl, setContentEl] = useState(null);
|
|
14
|
+
useRestoreInterruptedFocus(contentEl);
|
|
15
|
+
const focus = useModalFocus({
|
|
16
|
+
open,
|
|
17
|
+
initialFocus,
|
|
18
|
+
onOpenAutoFocus,
|
|
19
|
+
onCloseAutoFocus
|
|
20
|
+
});
|
|
21
|
+
const contextContainer = usePortalContainer();
|
|
22
|
+
const finalContainer = portalContainer ?? contextContainer ?? void 0;
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const raf = requestAnimationFrame(() => {
|
|
25
|
+
setDisplayed(open);
|
|
26
|
+
});
|
|
27
|
+
return () => cancelAnimationFrame(raf);
|
|
28
|
+
}, [open]);
|
|
29
|
+
const transformValue = {
|
|
30
|
+
top: "-translate-y-full",
|
|
31
|
+
bottom: "translate-y-full",
|
|
32
|
+
left: "-translate-x-full",
|
|
33
|
+
right: "translate-x-full"
|
|
34
|
+
};
|
|
35
|
+
const borderClass = {
|
|
36
|
+
top: "border-b",
|
|
37
|
+
bottom: "border-t",
|
|
38
|
+
left: "border-r",
|
|
39
|
+
right: "border-l"
|
|
40
|
+
};
|
|
41
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, {
|
|
42
|
+
open: displayed || open,
|
|
43
|
+
modal,
|
|
44
|
+
onOpenChange,
|
|
45
|
+
children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, {
|
|
46
|
+
container: finalContainer,
|
|
47
|
+
children: [includeBackgroundOverlay && /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
|
|
48
|
+
className: cls("outline-none", "fixed inset-0 bg-surface-scrim", "backdrop-blur-sm transition-all duration-100 motion-reduce:transition-none", overlayZIndex, overlayClassName),
|
|
49
|
+
style: overlayStyle
|
|
50
|
+
}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
|
|
51
|
+
...props,
|
|
52
|
+
ref: setContentEl,
|
|
53
|
+
onOpenAutoFocus: focus.onOpenAutoFocus,
|
|
54
|
+
onCloseAutoFocus: focus.onCloseAutoFocus,
|
|
55
|
+
onPointerDownOutside,
|
|
56
|
+
onInteractOutside,
|
|
57
|
+
className: cls("outline-none", borderClass[side], defaultBorderMixin, "text-surface-accent-900 dark:text-white", "fixed transform z-50 transition-[transform,opacity] ease-in-out motion-reduce:transition-none", !displayed ? "duration-150" : "duration-100", "outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0", transparent ? "" : "shadow-md bg-surface-card", side === "top" || side === "bottom" ? "w-full" : "h-full", side === "left" || side === "top" ? "left-0 top-0" : "right-0 bottom-0", displayed && open ? "opacity-100" : "opacity-50", !displayed || !open ? transformValue[side] : "", className),
|
|
58
|
+
style,
|
|
59
|
+
children: [/* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
60
|
+
className: "sr-only outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0",
|
|
61
|
+
children: title ?? "Sheet"
|
|
62
|
+
}), /* @__PURE__ */ jsx(PortalContainerProvider, {
|
|
63
|
+
container: contentEl,
|
|
64
|
+
children
|
|
65
|
+
})]
|
|
66
|
+
})]
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { Sheet };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=Sheet.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sheet.es.js","names":[],"sources":["../../src/components/Sheet.tsx"],"sourcesContent":["\"use client\";\nimport React, { useEffect, useState } from \"react\";\nimport { cls } from \"../util\";\nimport { defaultBorderMixin } from \"../styles\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { usePortalContainer, PortalContainerProvider } from \"../hooks/PortalContainerContext\";\nimport { useRestoreInterruptedFocus } from \"../hooks/useRestoreInterruptedFocus\";\nimport { useModalFocus } from \"../hooks/useModalFocus\";\n\ninterface SheetProps {\n children: React.ReactNode;\n open: boolean;\n title?: string;\n modal?: boolean;\n includeBackgroundOverlay?: boolean;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n darkBackground?: boolean;\n transparent?: boolean;\n onOpenChange?: (open: boolean) => void;\n onPointerDownOutside?: (e: Event) => void;\n onInteractOutside?: (e: Event) => void;\n /**\n * The element to focus when the sheet opens. Without it the sheet focuses\n * itself, so a screen reader announces it by its title and a phone does\n * not raise its keyboard.\n */\n initialFocus?: React.RefObject<HTMLElement | null>;\n /** Called as the sheet opens, before focus moves into it. `preventDefault()` keeps focus where it is. */\n onOpenAutoFocus?: (e: Event) => void;\n /**\n * Called when focus is about to return after the sheet closes. By default\n * it goes back to the element that had it when the sheet opened.\n */\n onCloseAutoFocus?: (e: Event) => void;\n className?: string;\n style?: React.CSSProperties;\n overlayClassName?: string;\n overlayZIndex?: string;\n overlayStyle?: React.CSSProperties;\n portalContainer?: HTMLElement | null;\n}\n\nexport const Sheet: React.FC<SheetProps> = ({\n children,\n side = \"right\",\n title,\n modal = true,\n includeBackgroundOverlay = true,\n open,\n onOpenChange,\n onPointerDownOutside,\n onInteractOutside,\n initialFocus,\n onOpenAutoFocus,\n onCloseAutoFocus,\n transparent,\n className,\n style,\n overlayClassName,\n overlayZIndex = \"z-50\",\n overlayStyle,\n portalContainer,\n ...props\n}) => {\n const [displayed, setDisplayed] = useState(false);\n const [contentEl, setContentEl] = useState<HTMLDivElement | null>(null);\n // Popups portal into the content, which is also the focus trap's container:\n // one closing on blur used to drop a Tab onto the panel itself.\n useRestoreInterruptedFocus(contentEl);\n const focus = useModalFocus({\n open,\n initialFocus,\n onOpenAutoFocus,\n onCloseAutoFocus\n });\n\n // Get the portal container from context\n const contextContainer = usePortalContainer();\n\n // Prioritize manual prop, fallback to context container\n const finalContainer = (portalContainer ?? contextContainer ?? undefined) as HTMLElement | undefined;\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => {\n setDisplayed(open);\n });\n return () => cancelAnimationFrame(raf);\n }, [open]);\n\n const transformValue: Record<string, string> = {\n top: \"-translate-y-full\",\n bottom: \"translate-y-full\",\n left: \"-translate-x-full\",\n right: \"translate-x-full\"\n };\n\n const borderClass: Record<string, string> = {\n top: \"border-b\",\n bottom: \"border-t\",\n left: \"border-r\",\n right: \"border-l\"\n };\n\n return (\n <DialogPrimitive.Root open={displayed || open}\n modal={modal}\n onOpenChange={onOpenChange}>\n <DialogPrimitive.Portal container={finalContainer}>\n {includeBackgroundOverlay && <DialogPrimitive.Overlay\n className={cls(\n \"outline-none\",\n \"fixed inset-0 bg-surface-scrim\",\n \"backdrop-blur-sm transition-all duration-100 motion-reduce:transition-none\",\n overlayZIndex,\n overlayClassName\n )}\n style={overlayStyle}\n />}\n <DialogPrimitive.Content\n {...props}\n ref={setContentEl}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n onPointerDownOutside={onPointerDownOutside}\n onInteractOutside={onInteractOutside}\n className={cls(\n \"outline-none\",\n borderClass[side],\n defaultBorderMixin,\n // No `will-change: transform` / `transform-gpu` here, however\n // tempting the layer hint is on a panel this size. Either one\n // makes this element a *containing block* for its\n // `position: fixed` descendants, and everything portaled into\n // the panel below — a Select dropdown, above all — is fixed and\n // positioned in viewport coordinates. Inside a containing block\n // those coordinates are resolved against the panel instead, so\n // every popup was displaced by the panel's own offset and a\n // right-hand Select opened its list off the edge of the screen:\n // the dropdown was open, just nowhere anyone could see it.\n \"text-surface-accent-900 dark:text-white\",\n \"fixed transform z-50 transition-[transform,opacity] ease-in-out motion-reduce:transition-none\",\n !displayed ? \"duration-150\" : \"duration-100\",\n \"outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0\",\n transparent ? \"\" : \"shadow-md bg-surface-card\",\n side === \"top\" || side === \"bottom\" ? \"w-full\" : \"h-full\",\n side === \"left\" || side === \"top\" ? \"left-0 top-0\" : \"right-0 bottom-0\",\n displayed && open ? \"opacity-100\" : \"opacity-50\",\n !displayed || !open ? transformValue[side] : \"\",\n className\n )}\n style={style}\n >\n <DialogPrimitive.Title className=\"sr-only outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus:ring-0\">\n {title ?? \"Sheet\"}\n </DialogPrimitive.Title>\n <PortalContainerProvider container={contentEl}>\n {children}\n </PortalContainerProvider>\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n );\n};\n"],"mappings":";;;;;;;;;;AA0CA,IAAa,SAA+B,EACxC,UACA,OAAO,SACP,OACA,QAAQ,MACR,2BAA2B,MAC3B,MACA,cACA,sBACA,mBACA,cACA,iBACA,kBACA,aACA,WACA,OACA,kBACA,gBAAgB,QAChB,cACA,iBACA,GAAG,YACD;CACF,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,WAAW,gBAAgB,SAAgC,IAAI;CAGtE,2BAA2B,SAAS;CACpC,MAAM,QAAQ,cAAc;EACxB;EACA;EACA;EACA;CACJ,CAAC;CAGD,MAAM,mBAAmB,mBAAmB;CAG5C,MAAM,iBAAkB,mBAAmB,oBAAoB,KAAA;CAE/D,gBAAgB;EACZ,MAAM,MAAM,4BAA4B;GACpC,aAAa,IAAI;EACrB,CAAC;EACD,aAAa,qBAAqB,GAAG;CACzC,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,iBAAyC;EAC3C,KAAK;EACL,QAAQ;EACR,MAAM;EACN,OAAO;CACX;CAEA,MAAM,cAAsC;EACxC,KAAK;EACL,QAAQ;EACR,MAAM;EACN,OAAO;CACX;CAEA,OACI,oBAAC,gBAAgB,MAAjB;EAAsB,MAAM,aAAa;EAC9B;EACO;YACd,qBAAC,gBAAgB,QAAjB;GAAwB,WAAW;aAAnC,CACK,4BAA4B,oBAAC,gBAAgB,SAAjB;IACzB,WAAW,IACP,gBACA,kCACA,8EACA,eACA,gBACJ;IACA,OAAO;GACV,CAAA,GACD,qBAAC,gBAAgB,SAAjB;IACI,GAAI;IACJ,KAAK;IACL,iBAAiB,MAAM;IACvB,kBAAkB,MAAM;IACF;IACH;IACnB,WAAW,IACP,gBACA,YAAY,OACZ,oBAWA,2CACA,iGACA,CAAC,YAAY,iBAAiB,gBAC9B,gGACA,cAAc,KAAK,6BACnB,SAAS,SAAS,SAAS,WAAW,WAAW,UACjD,SAAS,UAAU,SAAS,QAAQ,iBAAiB,oBACrD,aAAa,OAAO,gBAAgB,cACpC,CAAC,aAAa,CAAC,OAAO,eAAe,QAAQ,IAC7C,SACJ;IACO;cAhCX,CAkCI,oBAAC,gBAAgB,OAAjB;KAAuB,WAAU;eAC5B,SAAS;IACS,CAAA,GACvB,oBAAC,yBAAD;KAAyB,WAAW;KAC/B;IACoB,CAAA,CACJ;KACL;;CACN,CAAA;AAE9B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { cls } from "../util/cls.es.js";
|
|
2
|
+
import { useInjectStyles } from "../hooks/useInjectStyles.es.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/Skeleton.tsx
|
|
6
|
+
var styles = `
|
|
7
|
+
@keyframes shimmer {
|
|
8
|
+
0% {
|
|
9
|
+
transform: translateX(-150%);
|
|
10
|
+
}
|
|
11
|
+
100% {
|
|
12
|
+
transform: translateX(150%);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
function Skeleton({ width, height, className }) {
|
|
17
|
+
useInjectStyles("Skeleton", styles);
|
|
18
|
+
return /* @__PURE__ */ jsx("span", {
|
|
19
|
+
style: {
|
|
20
|
+
width: width === void 0 ? void 0 : `${width}px`,
|
|
21
|
+
height: height === void 0 ? void 0 : `${height}px`
|
|
22
|
+
},
|
|
23
|
+
className: cls("block relative overflow-hidden", "bg-surface-raised rounded-md", "max-w-full max-h-full", width === void 0 ? "w-full" : void 0, height === void 0 ? "h-3" : void 0, className),
|
|
24
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
25
|
+
className: "absolute inset-0 bg-gradient-to-r from-transparent via-white/50 dark:via-white/8 to-transparent",
|
|
26
|
+
style: { animation: "shimmer 1.8s ease-in-out infinite" }
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { Skeleton };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=Skeleton.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.es.js","names":[],"sources":["../../src/components/Skeleton.tsx"],"sourcesContent":["import React from \"react\";\nimport { cls } from \"../util\";\nimport { useInjectStyles } from \"../hooks\";\n\nexport type SkeletonProps = {\n width?: number;\n height?: number;\n className?: string;\n}\n\nconst styles = `\n@keyframes shimmer {\n 0% {\n transform: translateX(-150%);\n }\n 100% {\n transform: translateX(150%);\n }\n}\n`;\n\nexport function Skeleton({\n width,\n height,\n className\n }: SkeletonProps) {\n\n useInjectStyles(\"Skeleton\", styles);\n\n return <span\n style={{\n width: width === undefined ? undefined : `${width}px`,\n height: height === undefined ? undefined : `${height}px`\n }}\n className={\n cls(\n \"block relative overflow-hidden\",\n \"bg-surface-raised rounded-md\",\n \"max-w-full max-h-full\",\n // The defaults are classes, not inline styles, so that a caller can\n // override them: an inline style beats every utility, which is why\n // `<Skeleton className=\"w-full h-full\"/>` inside a 40px thumbnail\n // box used to render a 12px bar. The `width`/`height` props still\n // win over any class, since those do land inline.\n width === undefined ? \"w-full\" : undefined,\n height === undefined ? \"h-3\" : undefined,\n className)\n }>\n <span\n className=\"absolute inset-0 bg-gradient-to-r from-transparent via-white/50 dark:via-white/8 to-transparent\"\n style={{ animation: \"shimmer 1.8s ease-in-out infinite\" }}\n />\n </span>;\n}\n"],"mappings":";;;;;AAUA,IAAM,SAAS;;;;;;;;;;AAWf,SAAgB,SAAS,EACI,OACA,QACA,aACc;CAEvC,gBAAgB,YAAY,MAAM;CAElC,OAAO,oBAAC,QAAD;EACH,OAAO;GACH,OAAO,UAAU,KAAA,IAAY,KAAA,IAAY,GAAG,MAAM;GAClD,QAAQ,WAAW,KAAA,IAAY,KAAA,IAAY,GAAG,OAAO;EACzD;EACA,WACA,IACI,kCACA,gCACA,yBAMA,UAAU,KAAA,IAAY,WAAW,KAAA,GACjC,WAAW,KAAA,IAAY,QAAQ,KAAA,GAC/B,SAAS;YAEb,oBAAC,QAAD;GACI,WAAU;GACV,OAAO,EAAE,WAAW,oCAAoC;EAC3D,CAAA;CACC,CAAA;AACV"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cls } from "../util/cls.es.js";
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
6
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
7
|
+
//#region src/components/Slider.tsx
|
|
8
|
+
function SliderThumb(props) {
|
|
9
|
+
return /* @__PURE__ */ jsxs(TooltipPrimitive.Root, {
|
|
10
|
+
open: props.hovered,
|
|
11
|
+
children: [/* @__PURE__ */ jsx(TooltipPrimitive.Trigger, {
|
|
12
|
+
asChild: true,
|
|
13
|
+
children: /* @__PURE__ */ jsx(SliderPrimitive.Thumb, { className: cls({
|
|
14
|
+
"border-primary bg-primary outline-none": !props.props.disabled,
|
|
15
|
+
"border-surface-raised-hover bg-surface-raised-hover": props.props.disabled
|
|
16
|
+
}, props.classes, "focus-visible:ring-4 focus-visible:ring-primary focus-visible:ring-primary/50", "hover:ring-4 hover:ring-primary hover:ring-primary/25", "block rounded-full transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50") })
|
|
17
|
+
}), /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
|
|
18
|
+
side: "top",
|
|
19
|
+
sideOffset: 5,
|
|
20
|
+
className: cls("TooltipContent", "max-w-lg leading-relaxed", "z-50 rounded-md px-3 py-2 text-xs leading-none bg-surface-800/95 dark:bg-surface-raised-hover font-medium text-white shadow-2xl select-none duration-400 ease-in transform opacity-100"),
|
|
21
|
+
children: props.props.value?.[props.index]
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
var Slider = React$1.forwardRef(({ className, size = "regular", ...props }, ref) => {
|
|
26
|
+
const [hovered, setHovered] = React$1.useState(false);
|
|
27
|
+
const thumbSizeClasses = size === "small" ? "h-4 w-4" : "h-6 w-6";
|
|
28
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, {
|
|
29
|
+
delayDuration: 200,
|
|
30
|
+
children: /* @__PURE__ */ jsxs(SliderPrimitive.Root, {
|
|
31
|
+
ref,
|
|
32
|
+
onMouseEnter: () => setHovered(true),
|
|
33
|
+
onMouseLeave: () => setHovered(false),
|
|
34
|
+
className: cls("relative flex w-full touch-none select-none items-center", className),
|
|
35
|
+
...props,
|
|
36
|
+
children: [/* @__PURE__ */ jsx(SliderPrimitive.Track, {
|
|
37
|
+
style: { height: size === "small" ? 4 : 8 },
|
|
38
|
+
className: "relative w-full grow overflow-hidden rounded-full bg-surface-active",
|
|
39
|
+
children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: cls("absolute h-full", {
|
|
40
|
+
"bg-primary": !props.disabled,
|
|
41
|
+
"bg-surface-raised-hover": props.disabled
|
|
42
|
+
}) })
|
|
43
|
+
}), (props.value ?? props.defaultValue ?? [0]).map((_, index) => /* @__PURE__ */ jsx(SliderThumb, {
|
|
44
|
+
index,
|
|
45
|
+
props,
|
|
46
|
+
hovered,
|
|
47
|
+
classes: thumbSizeClasses
|
|
48
|
+
}, index))]
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
Slider.displayName = "Slider";
|
|
53
|
+
//#endregion
|
|
54
|
+
export { Slider };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=Slider.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.es.js","names":[],"sources":["../../src/components/Slider.tsx"],"sourcesContent":["\"use client\";\nimport * as React from \"react\";\nimport { cls } from \"../util\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nexport interface SliderProps {\n className?: string;\n name?: string;\n disabled?: boolean;\n orientation?: React.AriaAttributes[\"aria-orientation\"];\n dir?: \"ltr\" | \"rtl\";\n min?: number;\n max?: number;\n step?: number;\n minStepsBetweenThumbs?: number;\n value?: number[];\n defaultValue?: number[];\n onValueChange?: (value: number[]) => void;\n onValueCommit?: (value: number[]) => void;\n inverted?: boolean;\n form?: string;\n size?: \"small\" | \"regular\";\n}\n\nfunction SliderThumb(props: {\n props: Omit<React.PropsWithoutRef<SliderProps>, \"size\" | \"className\">,\n index: number,\n hovered: boolean,\n classes: string\n}) {\n return <TooltipPrimitive.Root open={props.hovered}>\n <TooltipPrimitive.Trigger asChild>\n <SliderPrimitive.Thumb\n className={cls({\n \"border-primary bg-primary outline-none\": !props.props.disabled,\n \"border-surface-raised-hover bg-surface-raised-hover\": props.props.disabled\n },\n props.classes,\n \"focus-visible:ring-4 focus-visible:ring-primary focus-visible:ring-primary/50\",\n \"hover:ring-4 hover:ring-primary hover:ring-primary/25\",\n \"block rounded-full transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50\")}\n\n />\n </TooltipPrimitive.Trigger>\n <TooltipPrimitive.Content side=\"top\"\n sideOffset={5}\n className={cls(\n \"TooltipContent\",\n \"max-w-lg leading-relaxed\",\n \"z-50 rounded-md px-3 py-2 text-xs leading-none bg-surface-800/95 dark:bg-surface-raised-hover font-medium text-white shadow-2xl select-none duration-400 ease-in transform opacity-100\"\n )}>\n {props.props.value?.[props.index]}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Root>;\n}\n\nconst Slider = React.forwardRef<\n React.ElementRef<typeof SliderPrimitive.Root>,\n SliderProps\n>(({\n className,\n size = \"regular\",\n ...props\n }, ref) => {\n const [hovered, setHovered] = React.useState(false);\n\n const thumbSizeClasses =\n size === \"small\"\n ? \"h-4 w-4\" // Smaller size for the thumb\n : \"h-6 w-6\"; // Default size\n\n return (\n <TooltipPrimitive.Provider delayDuration={200}>\n <SliderPrimitive.Root\n ref={ref}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n className={cls(\n \"relative flex w-full touch-none select-none items-center\",\n className\n )}\n {...props}\n >\n <SliderPrimitive.Track\n style={{ height: size === \"small\" ? 4 : 8 }}\n className={\"relative w-full grow overflow-hidden rounded-full bg-surface-active\"}>\n\n <SliderPrimitive.Range\n className={cls(\"absolute h-full\", {\n \"bg-primary\": !props.disabled,\n \"bg-surface-raised-hover\": props.disabled\n })}\n />\n </SliderPrimitive.Track>\n\n {(props.value ?? props.defaultValue ?? [0]).map((_, index) => <SliderThumb\n key={index}\n index={index}\n props={props}\n hovered={hovered}\n classes={thumbSizeClasses}/>)}\n </SliderPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n});\n\nSlider.displayName = \"Slider\";\n\nexport { Slider };\n"],"mappings":";;;;;;;AAyBA,SAAS,YAAY,OAKlB;CACC,OAAO,qBAAC,iBAAiB,MAAlB;EAAuB,MAAM,MAAM;YAAnC,CACH,oBAAC,iBAAiB,SAAlB;GAA0B,SAAA;aACtB,oBAAC,gBAAgB,OAAjB,EACI,WAAW,IAAI;IACP,0CAA0C,CAAC,MAAM,MAAM;IACvD,uDAAuD,MAAM,MAAM;GACvE,GACA,MAAM,SACN,iFACA,yDACA,kHAAkH,EAEzH,CAAA;EACqB,CAAA,GAC1B,oBAAC,iBAAiB,SAAlB;GAA0B,MAAK;GACL,YAAY;GACZ,WAAW,IACP,kBACA,4BACA,wLACJ;aACrB,MAAM,MAAM,QAAQ,MAAM;EACL,CAAA,CACP;;AAC3B;AAEA,IAAM,SAAS,QAAM,YAGlB,EACI,WACA,OAAO,WACP,GAAG,SACJ,QAAQ;CACV,MAAM,CAAC,SAAS,cAAc,QAAM,SAAS,KAAK;CAElD,MAAM,mBACF,SAAS,UACH,YACA;CAEV,OACI,oBAAC,iBAAiB,UAAlB;EAA2B,eAAe;YACtC,qBAAC,gBAAgB,MAAjB;GACS;GACL,oBAAoB,WAAW,IAAI;GACnC,oBAAoB,WAAW,KAAK;GACpC,WAAW,IACP,4DACA,SACJ;GACA,GAAI;aARR,CAUI,oBAAC,gBAAgB,OAAjB;IACI,OAAO,EAAE,QAAQ,SAAS,UAAU,IAAI,EAAE;IAC1C,WAAW;cAEX,oBAAC,gBAAgB,OAAjB,EACI,WAAW,IAAI,mBAAmB;KAC9B,cAAc,CAAC,MAAM;KACrB,2BAA2B,MAAM;IACrC,CAAC,EACJ,CAAA;GACkB,CAAA,IAErB,MAAM,SAAS,MAAM,gBAAgB,CAAC,CAAC,EAAA,CAAG,KAAK,GAAG,UAAU,oBAAC,aAAD;IAEnD;IACA;IACE;IACT,SAAS;GAAkB,GAJtB,KAIsB,CAAC,CACd;;CACC,CAAA;AAEnC,CAAC;AAED,OAAO,cAAc"}
|