@olenbetong/appframe-ds 0.5.0 → 0.7.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/CHANGELOG.md +22 -0
- package/package.json +11 -9
- package/scripts/copyAssets.mjs +10 -1
- package/src/AfLookup/Lookup.tsx +7 -8
- package/src/AfLookup/{Combobox.tsx → LookupCombobox.tsx} +8 -8
- package/src/AfLookup/LookupEdit.tsx +5 -6
- package/src/AfLookup/index.ts +1 -1
- package/src/autocomplete/Autocomplete.css +222 -0
- package/src/autocomplete/Autocomplete.tsx +316 -0
- package/src/autocomplete/AutocompleteFrame.tsx +149 -0
- package/src/autocomplete/Combobox.tsx +260 -0
- package/src/autocomplete/index.ts +4 -0
- package/src/autocomplete/types.ts +200 -0
- package/src/autocomplete/utils.ts +183 -0
- package/src/binding/CancelButton.tsx +4 -1
- package/src/binding/CancelIconButton.tsx +2 -2
- package/src/binding/DataEditToolbar.tsx +1 -2
- package/src/binding/DeleteButton.tsx +6 -2
- package/src/binding/DeleteIconButton.tsx +5 -4
- package/src/binding/RefreshButton.tsx +7 -3
- package/src/binding/RefreshIconButton.tsx +6 -5
- package/src/binding/RefreshRowIconButton.tsx +6 -5
- package/src/binding/SaveButton.tsx +14 -4
- package/src/binding/SaveIconButton.tsx +13 -6
- package/src/index.ts +4 -0
- package/src/input/InputAdornments.css +75 -0
- package/src/input/InputAdornments.tsx +97 -0
- package/src/input/index.ts +1 -0
- package/src/progress/LinearProgress.css +93 -0
- package/src/progress/LinearProgress.tsx +104 -0
- package/src/progress/index.ts +1 -0
- package/src/sortable/DropIndicator.css +51 -0
- package/src/sortable/DropIndicator.tsx +27 -0
- package/src/sortable/SortableItemList.css +21 -0
- package/src/sortable/SortableItemList.tsx +264 -0
- package/src/sortable/index.ts +8 -0
- package/src/sortable/reorderSortOrder.ts +126 -0
- package/src/sortable/sortOrder.ts +101 -0
- package/src/sortable/types.ts +9 -0
- package/src/sortable/useSortableContainer.ts +53 -0
- package/src/sortable/useSortableItem.ts +95 -0
- package/src/sortable/useSortableList.ts +117 -0
- /package/src/AfLookup/{Combobox.css → LookupCombobox.css} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @olenbetong/appframe-ds
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 52e2e10: Add `Autocomplete` and `Combobox`, built on the Base UI components of the same name and styled with Designsystemet tokens. Both expose an API close to MUI's `Autocomplete` (`options`, `value`/`onChange`, `inputValue`/`onInputChange`, `getOptionLabel`, `isOptionEqualToValue`, `filterOptions`, `renderOption`, `groupBy`, `multiple`), plus Designsystemet field props (`label`, `description`, `error`, `data-size`). Use `Combobox` when the user must pick one of the options and `Autocomplete` when free text is allowed (`freeSolo`). Multiple selection renders the selected options as chips above the input, like Designsystemet's `Suggestion`. `createFilterOptions` is exported for custom filtering.
|
|
8
|
+
|
|
9
|
+
**Breaking:** the data object bound `Combobox` used internally by `AfLookup` is renamed to `LookupCombobox` (`ComboboxProps` → `LookupComboboxProps`) to free up the `Combobox` name.
|
|
10
|
+
|
|
11
|
+
- 77e96aa: Add `SortableItemList`, an `ItemList` variant bound to a data object where items can be reordered by dragging or through a menu on the drag handle. The building blocks are exported as well (`useSortableList`, `useSortableItem`, `useSortableContainer`, `DropIndicator`, `reorderSortOrder`, `getNextSortOrder`, `ensureNonZeroSortOrder`) for lists that need custom item markup.
|
|
12
|
+
|
|
13
|
+
## 0.6.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- 0147e80: Add `LinearProgress` component: a designsystemet-styled linear progress bar equivalent to MUI `LinearProgress`, with indeterminate and determinate modes and an `overlay` prop for an absolutely positioned bar that does not affect the layout.
|
|
18
|
+
- 56080ed: Add `InputAdornments` and `InputSlot`: an input with adornments (MUI `TextField` start/end adornment equivalent) where the border, background, hover and focus styling lives on a wrapper around the input and its adornments. Adornments are passed as children, and `InputSlot` controls where the input is placed (defaults to the start).
|
|
19
|
+
- bc89c1e: Migrated all icons in appframe-ds from `@mui/icons-material` to `@navikt/aksel-icons`. Bound action buttons (`SaveButton`, `DeleteButton`, `CancelButton`, `RefreshButton` and their icon-only variants) now show a leading icon that is hidden while loading, so button width no longer changes when toggling the loading state. `SaveButton` and `SaveIconButton` also display a small warning badge on the save icon when the current record has unsaved changes, matching the existing appframe-mui behavior.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 0147e80: Make the indeterminate `LinearProgress` animation more visible by using a single travelling bar that stretches and shrinks, instead of the two subtle MUI-style bars.
|
|
24
|
+
|
|
3
25
|
## 0.5.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-ds",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Components that bind Designsystemet components to Appframe data objects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./es/index.d.ts",
|
|
@@ -16,25 +16,28 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"@digdir/designsystemet-react": ">=1.18.0",
|
|
19
|
-
"@
|
|
19
|
+
"@navikt/aksel-icons": ">=8.16.1",
|
|
20
20
|
"react": ">=19.2.8",
|
|
21
21
|
"react-dom": ">=19.2.8",
|
|
22
22
|
"react-error-boundary": ">=6.1.2",
|
|
23
23
|
"react-router": ">=8.3.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@atlaskit/pragmatic-drag-and-drop": "2.0.1",
|
|
27
|
+
"@atlaskit/pragmatic-drag-and-drop-hitbox": "2.0.0",
|
|
28
|
+
"@base-ui/react": "1.7.0",
|
|
26
29
|
"@olenbetong/appframe-core": "2.11.10",
|
|
27
30
|
"@olenbetong/appframe-data": "1.5.0",
|
|
28
|
-
"@olenbetong/appframe-react": "
|
|
29
|
-
"
|
|
31
|
+
"@olenbetong/appframe-react": "2.0.0",
|
|
32
|
+
"clsx": "^2.1.1",
|
|
30
33
|
"react-virtualized-auto-sizer": "^1.0.26",
|
|
31
|
-
"
|
|
34
|
+
"react-window": "^1.8.11"
|
|
32
35
|
},
|
|
33
36
|
"devDependencies": {
|
|
34
37
|
"@digdir/designsystemet-react": "1.18.0",
|
|
35
|
-
"@
|
|
36
|
-
"@types/react": "19.2.
|
|
37
|
-
"@types/react-dom": "19.2.
|
|
38
|
+
"@navikt/aksel-icons": "8.16.1",
|
|
39
|
+
"@types/react": "19.2.18",
|
|
40
|
+
"@types/react-dom": "19.2.4",
|
|
38
41
|
"@types/react-window": "^1.8.8",
|
|
39
42
|
"react": "19.2.8",
|
|
40
43
|
"react-dom": "19.2.8",
|
|
@@ -42,7 +45,6 @@
|
|
|
42
45
|
"react-router": "8.3.0",
|
|
43
46
|
"typescript": "7.0.2"
|
|
44
47
|
},
|
|
45
|
-
"optionalDependencies": {},
|
|
46
48
|
"scripts": {
|
|
47
49
|
"build": "pnpm run build:tsc && pnpm run build:css",
|
|
48
50
|
"build:tsc": "node --no-warnings ../../scripts/clean.ts ./es tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json",
|
package/scripts/copyAssets.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { cpSync, mkdirSync } from "node:fs";
|
|
|
3
3
|
const files = [
|
|
4
4
|
["src/AfLookup/Lookup.css", "es/AfLookup/Lookup.css"],
|
|
5
5
|
["src/AfLookup/LookupGrid.css", "es/AfLookup/LookupGrid.css"],
|
|
6
|
-
["src/AfLookup/
|
|
6
|
+
["src/AfLookup/LookupCombobox.css", "es/AfLookup/LookupCombobox.css"],
|
|
7
7
|
["src/layout/AppMenu.css", "es/layout/AppMenu.css"],
|
|
8
8
|
["src/layout/AppMenuItem.css", "es/layout/AppMenuItem.css"],
|
|
9
9
|
["src/layout/AppMenuSubheader.css", "es/layout/AppMenuSubheader.css"],
|
|
@@ -16,13 +16,22 @@ const files = [
|
|
|
16
16
|
["src/page/PageBlock.css", "es/page/PageBlock.css"],
|
|
17
17
|
["src/page/PageHeader.css", "es/page/PageHeader.css"],
|
|
18
18
|
["src/list/ItemList.css", "es/list/ItemList.css"],
|
|
19
|
+
["src/input/InputAdornments.css", "es/input/InputAdornments.css"],
|
|
19
20
|
["src/paper/Paper.css", "es/paper/Paper.css"],
|
|
21
|
+
["src/progress/LinearProgress.css", "es/progress/LinearProgress.css"],
|
|
22
|
+
["src/sortable/DropIndicator.css", "es/sortable/DropIndicator.css"],
|
|
23
|
+
["src/sortable/SortableItemList.css", "es/sortable/SortableItemList.css"],
|
|
24
|
+
["src/autocomplete/Autocomplete.css", "es/autocomplete/Autocomplete.css"],
|
|
20
25
|
];
|
|
21
26
|
|
|
22
27
|
mkdirSync("es/layout", { recursive: true });
|
|
28
|
+
mkdirSync("es/input", { recursive: true });
|
|
23
29
|
mkdirSync("es/list", { recursive: true });
|
|
24
30
|
mkdirSync("es/page", { recursive: true });
|
|
25
31
|
mkdirSync("es/paper", { recursive: true });
|
|
32
|
+
mkdirSync("es/progress", { recursive: true });
|
|
33
|
+
mkdirSync("es/sortable", { recursive: true });
|
|
34
|
+
mkdirSync("es/autocomplete", { recursive: true });
|
|
26
35
|
|
|
27
36
|
for (let [src, dest] of files) {
|
|
28
37
|
cpSync(src, dest);
|
package/src/AfLookup/Lookup.tsx
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import "./Lookup.css";
|
|
2
2
|
|
|
3
3
|
import { Button, Textfield, type TextfieldProps } from "@digdir/designsystemet-react";
|
|
4
|
-
import
|
|
5
|
-
import SearchIcon from "@mui/icons-material/Search";
|
|
4
|
+
import { MagnifyingGlassIcon, XMarkIcon } from "@navikt/aksel-icons";
|
|
6
5
|
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
7
6
|
import { type DistributiveOmit, useLookupState } from "@olenbetong/appframe-react";
|
|
8
7
|
|
|
@@ -10,9 +9,9 @@ import clsx from "clsx";
|
|
|
10
9
|
import { useRef } from "react";
|
|
11
10
|
import { createPortal } from "react-dom";
|
|
12
11
|
|
|
13
|
-
import {
|
|
12
|
+
import { LookupCombobox, type LookupComboboxProps } from "./LookupCombobox.js";
|
|
14
13
|
|
|
15
|
-
export type AfLookupProps<T extends Record<string, unknown>> = DistributiveOmit<
|
|
14
|
+
export type AfLookupProps<T extends Record<string, unknown>> = DistributiveOmit<LookupComboboxProps<T>, "value"> & {
|
|
16
15
|
/**
|
|
17
16
|
* Allows the user to enter a value manually that might not be in the list.
|
|
18
17
|
*/
|
|
@@ -27,7 +26,7 @@ export type AfLookupProps<T extends Record<string, unknown>> = DistributiveOmit<
|
|
|
27
26
|
};
|
|
28
27
|
};
|
|
29
28
|
|
|
30
|
-
export type LookupProps<T extends Record<string, unknown>> = DistributiveOmit<
|
|
29
|
+
export type LookupProps<T extends Record<string, unknown>> = DistributiveOmit<LookupComboboxProps<T>, "value"> & {
|
|
31
30
|
slotProps?: {
|
|
32
31
|
dialog?: Partial<React.HTMLProps<HTMLDialogElement>>;
|
|
33
32
|
};
|
|
@@ -71,7 +70,7 @@ export function useLookup<T extends Record<string, unknown>>({
|
|
|
71
70
|
style={{ positionAnchor: anchorName, ...slotProps?.dialog?.style } as React.CSSProperties}
|
|
72
71
|
>
|
|
73
72
|
{open && (
|
|
74
|
-
<
|
|
73
|
+
<LookupCombobox
|
|
75
74
|
{...props}
|
|
76
75
|
initialSearchValue={initialSearchValueRef.current}
|
|
77
76
|
onClose={() => dialogRef.current?.close()}
|
|
@@ -143,7 +142,7 @@ export function AfLookup<T extends Record<string, unknown>>({
|
|
|
143
142
|
document.getElementById(inputId)?.focus();
|
|
144
143
|
}}
|
|
145
144
|
>
|
|
146
|
-
<
|
|
145
|
+
<XMarkIcon />
|
|
147
146
|
</Button>
|
|
148
147
|
)}
|
|
149
148
|
<Button
|
|
@@ -153,7 +152,7 @@ export function AfLookup<T extends Record<string, unknown>>({
|
|
|
153
152
|
aria-label={getLocalizedString("Search")}
|
|
154
153
|
onClick={() => openDialog()}
|
|
155
154
|
>
|
|
156
|
-
<
|
|
155
|
+
<MagnifyingGlassIcon />
|
|
157
156
|
</Button>
|
|
158
157
|
</div>
|
|
159
158
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./
|
|
1
|
+
import "./LookupCombobox.css";
|
|
2
2
|
|
|
3
3
|
import { Button, Textfield } from "@digdir/designsystemet-react";
|
|
4
4
|
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
@@ -11,7 +11,7 @@ import { VariableSizeList as VirtualList } from "react-window";
|
|
|
11
11
|
|
|
12
12
|
import { LookupGrid } from "./LookupGrid.js";
|
|
13
13
|
|
|
14
|
-
export interface
|
|
14
|
+
export interface LookupComboboxBaseProps<T extends Record<string, unknown>> {
|
|
15
15
|
nullable?: boolean;
|
|
16
16
|
dataObject: DataObject<T>;
|
|
17
17
|
uniqueIdField?: string;
|
|
@@ -22,7 +22,7 @@ export interface ComboboxBaseProps<T extends Record<string, unknown>> {
|
|
|
22
22
|
onClose?: () => void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export interface
|
|
25
|
+
export interface LookupComboboxListProps<T extends Record<string, unknown>> extends LookupComboboxBaseProps<T> {
|
|
26
26
|
/**
|
|
27
27
|
* Renders the popup content as a list (default).
|
|
28
28
|
*/
|
|
@@ -30,7 +30,7 @@ export interface ComboboxListProps<T extends Record<string, unknown>> extends Co
|
|
|
30
30
|
renderItem: (props: React.ComponentPropsWithRef<"li"> & { item: T }) => React.ReactNode;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export interface
|
|
33
|
+
export interface LookupComboboxGridProps<T extends Record<string, unknown>> extends LookupComboboxBaseProps<T> {
|
|
34
34
|
/**
|
|
35
35
|
* Renders the popup content as a grid with a header row and one column per
|
|
36
36
|
* entry in `columns`.
|
|
@@ -39,9 +39,9 @@ export interface ComboboxGridProps<T extends Record<string, unknown>> extends Co
|
|
|
39
39
|
columns: LookupColumn<T>[];
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export type
|
|
42
|
+
export type LookupComboboxProps<T extends Record<string, unknown>> = LookupComboboxListProps<T> | LookupComboboxGridProps<T>;
|
|
43
43
|
|
|
44
|
-
export function
|
|
44
|
+
export function LookupCombobox<T extends Record<string, unknown>>(props: LookupComboboxProps<T>) {
|
|
45
45
|
let {
|
|
46
46
|
nullable,
|
|
47
47
|
dataObject,
|
|
@@ -52,7 +52,7 @@ export function Combobox<T extends Record<string, unknown>>(props: ComboboxProps
|
|
|
52
52
|
onClose,
|
|
53
53
|
} = props;
|
|
54
54
|
let isGrid = props.variant === "grid";
|
|
55
|
-
let columns = isGrid ? (props as
|
|
55
|
+
let columns = isGrid ? (props as LookupComboboxGridProps<T>).columns : undefined;
|
|
56
56
|
let listRef = useRef<VirtualList>(null);
|
|
57
57
|
|
|
58
58
|
let [isDesktop, setIsDesktop] = useState(
|
|
@@ -121,7 +121,7 @@ export function Combobox<T extends Record<string, unknown>>(props: ComboboxProps
|
|
|
121
121
|
let item = data[index];
|
|
122
122
|
let itemId = getItemId(item);
|
|
123
123
|
let active = index === currentIndex;
|
|
124
|
-
let ItemComponent = (props as
|
|
124
|
+
let ItemComponent = (props as LookupComboboxListProps<T>).renderItem;
|
|
125
125
|
|
|
126
126
|
return (
|
|
127
127
|
<ItemComponent
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import "./Lookup.css";
|
|
2
2
|
|
|
3
3
|
import { Button, Textfield, type TextfieldProps } from "@digdir/designsystemet-react";
|
|
4
|
-
import
|
|
5
|
-
import SearchIcon from "@mui/icons-material/Search";
|
|
4
|
+
import { MagnifyingGlassIcon, XMarkIcon } from "@navikt/aksel-icons";
|
|
6
5
|
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
7
6
|
import type { DistributiveOmit } from "@olenbetong/appframe-react";
|
|
8
7
|
|
|
9
8
|
import clsx from "clsx";
|
|
10
9
|
import type React from "react";
|
|
11
10
|
|
|
12
|
-
import type {
|
|
11
|
+
import type { LookupComboboxProps } from "./LookupCombobox.js";
|
|
13
12
|
import { useLookup } from "./Lookup.js";
|
|
14
13
|
|
|
15
14
|
export type AfLookupEditProps<T extends Record<string, unknown>> = DistributiveOmit<
|
|
16
|
-
|
|
15
|
+
LookupComboboxProps<T>,
|
|
17
16
|
"value" | "onChange"
|
|
18
17
|
> & {
|
|
19
18
|
/**
|
|
@@ -108,7 +107,7 @@ export function AfLookupEdit<T extends Record<string, unknown>>({
|
|
|
108
107
|
document.getElementById(inputId)?.focus();
|
|
109
108
|
}}
|
|
110
109
|
>
|
|
111
|
-
<
|
|
110
|
+
<XMarkIcon />
|
|
112
111
|
</Button>
|
|
113
112
|
)}
|
|
114
113
|
<Button
|
|
@@ -121,7 +120,7 @@ export function AfLookupEdit<T extends Record<string, unknown>>({
|
|
|
121
120
|
openDialog();
|
|
122
121
|
}}
|
|
123
122
|
>
|
|
124
|
-
<
|
|
123
|
+
<MagnifyingGlassIcon />
|
|
125
124
|
</Button>
|
|
126
125
|
</div>
|
|
127
126
|
</div>
|
package/src/AfLookup/index.ts
CHANGED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
.ObAutocomplete-root {
|
|
2
|
+
--obAutocomplete-padding: 0.25rem;
|
|
3
|
+
--obAutocomplete-gap: 0.25rem;
|
|
4
|
+
--obAutocomplete-fontSize: var(--ds-font-size-3, 1rem);
|
|
5
|
+
|
|
6
|
+
display: inline-grid;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ObAutocomplete-root[data-full-width="true"] {
|
|
10
|
+
display: grid;
|
|
11
|
+
inline-size: 100%;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ObAutocomplete-root[data-size="xs"] {
|
|
15
|
+
--obAutocomplete-padding: 0.125rem;
|
|
16
|
+
--obAutocomplete-fontSize: var(--ds-font-size-1, 0.75rem);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.ObAutocomplete-root[data-size="sm"] {
|
|
20
|
+
--obAutocomplete-padding: 0.25rem;
|
|
21
|
+
--obAutocomplete-fontSize: var(--ds-font-size-2, 0.875rem);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ObAutocomplete-root[data-size="md"] {
|
|
25
|
+
--obAutocomplete-padding: 0.25rem;
|
|
26
|
+
--obAutocomplete-fontSize: var(--ds-font-size-3, 1rem);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ObAutocomplete-root[data-size="lg"] {
|
|
30
|
+
--obAutocomplete-padding: 0.375rem;
|
|
31
|
+
--obAutocomplete-fontSize: var(--ds-font-size-4, 1.125rem);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The control is the visual input: it owns the border, background, hover and
|
|
36
|
+
* focus styling, so the chips, the bare input and the buttons read as a single
|
|
37
|
+
* control. Mirrors how Designsystemet's Suggestion renders selected chips
|
|
38
|
+
* above the input.
|
|
39
|
+
*/
|
|
40
|
+
.ObAutocomplete-control {
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
gap: var(--obAutocomplete-gap);
|
|
45
|
+
padding: var(--obAutocomplete-padding);
|
|
46
|
+
inline-size: 100%;
|
|
47
|
+
font-size: var(--obAutocomplete-fontSize);
|
|
48
|
+
color: var(--ds-color-neutral-text-default, #1e2b3c);
|
|
49
|
+
background-color: var(--ds-color-neutral-surface-default, #fff);
|
|
50
|
+
border: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-default, #b3b3b3);
|
|
51
|
+
border-radius: var(--ds-border-radius-md, 0.375rem);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.ObAutocomplete-control:hover:not(:focus-within) {
|
|
55
|
+
border-color: var(--ds-color-neutral-border-strong, #767676);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ObAutocomplete-control:has(.ObAutocomplete-input:focus-visible) {
|
|
59
|
+
box-shadow: var(--dsc-focus-boxShadow);
|
|
60
|
+
outline: var(--dsc-focus-outline);
|
|
61
|
+
outline-offset: var(--ds-border-width-focus, 3px);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ObAutocomplete-control[data-invalid="true"] {
|
|
65
|
+
border-color: var(--ds-color-danger-border-default, #b3253a);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.ObAutocomplete-control[data-disabled="true"] {
|
|
69
|
+
cursor: not-allowed;
|
|
70
|
+
opacity: var(--ds-disabled-opacity, 0.3);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.ObAutocomplete-chips {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-wrap: wrap;
|
|
76
|
+
gap: var(--obAutocomplete-gap);
|
|
77
|
+
padding: var(--obAutocomplete-padding);
|
|
78
|
+
padding-block-end: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.ObAutocomplete-inputGroup {
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: var(--obAutocomplete-gap);
|
|
85
|
+
min-inline-size: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.ObAutocomplete-input {
|
|
89
|
+
flex: 1;
|
|
90
|
+
min-inline-size: 0;
|
|
91
|
+
padding: var(--ds-size-1, 0.25rem);
|
|
92
|
+
font: inherit;
|
|
93
|
+
color: inherit;
|
|
94
|
+
background: transparent;
|
|
95
|
+
border: none;
|
|
96
|
+
outline: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.ObAutocomplete-input:disabled {
|
|
100
|
+
cursor: not-allowed;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.ObAutocomplete-button {
|
|
104
|
+
display: inline-flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
flex: none;
|
|
108
|
+
padding: var(--ds-size-1, 0.25rem);
|
|
109
|
+
font-size: var(--obAutocomplete-fontSize);
|
|
110
|
+
color: inherit;
|
|
111
|
+
background: transparent;
|
|
112
|
+
border: none;
|
|
113
|
+
border-radius: var(--ds-border-radius-sm, 0.25rem);
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.ObAutocomplete-button:hover:not(:disabled) {
|
|
118
|
+
background-color: var(--ds-color-neutral-surface-hover, #e6e6e6);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.ObAutocomplete-button:disabled {
|
|
122
|
+
cursor: not-allowed;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.ObAutocomplete-button[data-visible="false"] {
|
|
126
|
+
display: none;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.ObAutocomplete-trigger[data-popup-open] svg {
|
|
130
|
+
rotate: 180deg;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.ObAutocomplete-spinner {
|
|
134
|
+
flex: none;
|
|
135
|
+
display: inline-flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
padding-inline: var(--ds-size-1, 0.25rem);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.ObAutocomplete-positioner {
|
|
141
|
+
z-index: 1500;
|
|
142
|
+
/* Base UI renders the positioner even while closed */
|
|
143
|
+
outline: none;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.ObAutocomplete-popup {
|
|
147
|
+
box-sizing: border-box;
|
|
148
|
+
inline-size: var(--anchor-width);
|
|
149
|
+
max-block-size: min(24rem, var(--available-height));
|
|
150
|
+
overflow-y: auto;
|
|
151
|
+
overscroll-behavior: contain;
|
|
152
|
+
padding: var(--ds-size-1, 0.25rem);
|
|
153
|
+
font-size: var(--obAutocomplete-fontSize, var(--ds-font-size-3, 1rem));
|
|
154
|
+
color: var(--ds-color-neutral-text-default, #1e2b3c);
|
|
155
|
+
background-color: var(--ds-color-neutral-background-default, #fff);
|
|
156
|
+
border: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #e0e0e0);
|
|
157
|
+
border-radius: var(--ds-border-radius-md, 0.375rem);
|
|
158
|
+
box-shadow: var(--ds-shadow-md, 0 2px 8px 0 rgb(0 0 0 / 0.12));
|
|
159
|
+
transform-origin: var(--transform-origin);
|
|
160
|
+
transition:
|
|
161
|
+
opacity 0.12s ease-out,
|
|
162
|
+
scale 0.12s ease-out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.ObAutocomplete-popup[data-starting-style],
|
|
166
|
+
.ObAutocomplete-popup[data-ending-style] {
|
|
167
|
+
opacity: 0;
|
|
168
|
+
scale: 0.98;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.ObAutocomplete-list {
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.ObAutocomplete-item {
|
|
177
|
+
display: flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
gap: var(--ds-size-2, 0.5rem);
|
|
180
|
+
padding: var(--ds-size-2, 0.5rem);
|
|
181
|
+
border-radius: var(--ds-border-radius-sm, 0.25rem);
|
|
182
|
+
cursor: default;
|
|
183
|
+
user-select: none;
|
|
184
|
+
scroll-margin-block: var(--ds-size-1, 0.25rem);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.ObAutocomplete-item[data-highlighted] {
|
|
188
|
+
background-color: var(--ds-color-accent-surface-hover, #d6e2f2);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.ObAutocomplete-item[data-selected] {
|
|
192
|
+
font-weight: var(--ds-font-weight-medium, 500);
|
|
193
|
+
background-color: var(--ds-color-accent-surface-default, #e6effa);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.ObAutocomplete-item[data-selected][data-highlighted] {
|
|
197
|
+
background-color: var(--ds-color-accent-surface-active, #c2d5ec);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.ObAutocomplete-item[data-disabled] {
|
|
201
|
+
cursor: not-allowed;
|
|
202
|
+
opacity: var(--ds-disabled-opacity, 0.3);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.ObAutocomplete-itemIndicator {
|
|
206
|
+
display: inline-flex;
|
|
207
|
+
flex: none;
|
|
208
|
+
inline-size: 1em;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.ObAutocomplete-groupLabel {
|
|
212
|
+
padding: var(--ds-size-2, 0.5rem);
|
|
213
|
+
font-size: var(--ds-font-size-1, 0.75rem);
|
|
214
|
+
font-weight: var(--ds-font-weight-semibold, 600);
|
|
215
|
+
color: var(--ds-color-neutral-text-subtle, #4c5866);
|
|
216
|
+
text-transform: uppercase;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.ObAutocomplete-empty:not(:empty) {
|
|
220
|
+
padding: var(--ds-size-2, 0.5rem);
|
|
221
|
+
color: var(--ds-color-neutral-text-subtle, #4c5866);
|
|
222
|
+
}
|