@olenbetong/appframe-ds 1.9.0 → 1.9.1

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @olenbetong/appframe-ds
2
2
 
3
+ ## 1.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 0f57479: Lookups: the dialog lines up with the input instead of the label beside or above it, grows upwards when it is placed above the field, and follows the field's size mode also when opened with ArrowDown or F4. `GridEditLookup` takes `editable`, so a value can be typed into the cell.
8
+
3
9
  ## 1.9.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olenbetong/appframe-ds",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "Components that bind Designsystemet components to Appframe data objects",
5
5
  "type": "module",
6
6
  "types": "./es/index.d.ts",
@@ -3,6 +3,8 @@
3
3
 
4
4
  .ds-input {
5
5
  padding-inline-end: var(--ObLookup-buttons-width, var(--ds-size-12, 3rem));
6
+ /* Set by AfLookup and AfLookupEdit; the dialog lines up with the input, not its label. */
7
+ anchor-name: var(--ObLookup-anchor);
6
8
  }
7
9
  }
8
10
 
@@ -144,6 +146,11 @@
144
146
  }
145
147
  }
146
148
 
149
+ /* Placed above the field (see useLookup): grow upwards from it. */
150
+ &[data-above] {
151
+ transform-origin: bottom left;
152
+ }
153
+
147
154
  &[data-anchor="manual"] {
148
155
  inset: unset;
149
156
  position: fixed;
@@ -78,12 +78,38 @@ export function useLookup<T extends Record<string, unknown>>({
78
78
  // mounts with the search value already set.
79
79
  setInitialSearchValue(searchValue);
80
80
  openDialog();
81
+ setGrowDirection();
82
+ // A manually anchored dialog (in a virtualized grid) is placed in the next frame.
83
+ requestAnimationFrame(setGrowDirection);
84
+ }
85
+
86
+ // When there is no room below the field, the dialog is placed above it; it then grows upwards
87
+ // from the field instead of down towards it. Its bottom edge tells, whatever the opening scale.
88
+ function setGrowDirection() {
89
+ let $dialog = dialogRef.current;
90
+ let anchor = document.getElementById(inputId) ?? getAnchorElement?.();
91
+ if (!$dialog || !anchor) return;
92
+
93
+ let above = $dialog.getBoundingClientRect().bottom <= anchor.getBoundingClientRect().top + 1;
94
+ $dialog.toggleAttribute("data-above", above);
95
+ }
96
+
97
+ // useLookupState opens the dialog on ArrowDown and F4 itself, which would skip the size mode and
98
+ // the grow direction above; every way of opening it goes through handleOpenDialog instead.
99
+ function handleKeyDown(event: React.KeyboardEvent<HTMLElement>) {
100
+ if (event.key === "ArrowDown" || event.key === "F4") {
101
+ event.preventDefault();
102
+ event.stopPropagation();
103
+ handleOpenDialog();
104
+ return;
105
+ }
106
+ onKeyDown(event);
81
107
  }
82
108
 
83
109
  return {
84
110
  open,
85
111
  openDialog: handleOpenDialog,
86
- onKeyDown,
112
+ onKeyDown: handleKeyDown,
87
113
  onChange: handleChange,
88
114
  dialogRef,
89
115
  anchorName,
@@ -135,7 +161,8 @@ export function AfLookup<T extends Record<string, unknown>>({
135
161
  }
136
162
 
137
163
  return (
138
- <div style={{ anchorName } as React.CSSProperties}>
164
+ // The dialog anchors to the input itself (see Lookup.css), not to the label beside or above it.
165
+ <div style={{ "--ObLookup-anchor": anchorName } as React.CSSProperties}>
139
166
  <div
140
167
  className="ObLookup-inputWrap"
141
168
  style={
@@ -73,7 +73,8 @@ export function AfLookupEdit<T extends Record<string, unknown>>({
73
73
  let hasClear = !!(nullable && value && onChange);
74
74
 
75
75
  return (
76
- <div style={{ anchorName } as React.CSSProperties}>
76
+ // The dialog anchors to the input itself (see Lookup.css), not to the label beside or above it.
77
+ <div style={{ "--ObLookup-anchor": anchorName } as React.CSSProperties}>
77
78
  <div
78
79
  className="ObLookup-inputWrap"
79
80
  style={
@@ -22,7 +22,8 @@ export type GridEditLookupProps<
22
22
 
23
23
  /**
24
24
  * A lookup as a grid cell editor: a read-only input with a search button that opens the
25
- * lookup dialog anchored to the cell, and a clear button when the field is nullable. Give it
25
+ * lookup dialog anchored to the cell, and a clear button when the field is nullable. With
26
+ * `editable` the value can be typed into the cell as well, such as a username. Give it
26
27
  * to a column's `renderEditCell`. Equivalent of `GridEditLookup` in `@olenbetong/appframe-mui`.
27
28
  */
28
29
  export function GridEditLookup<
@@ -77,7 +78,7 @@ export function GridEditLookup<
77
78
  slotProps={{
78
79
  root: {
79
80
  // @ts-expect-error: typed as HTMLElement, but it is the input
80
- readOnly: true,
81
+ readOnly: !props.editable,
81
82
  },
82
83
  }}
83
84
  onKeyDown={onKeyDown}