@olenbetong/appframe-ds 1.6.1 → 1.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.
@@ -140,8 +140,8 @@
140
140
 
141
141
  /* The funnel is highlighted while the column has criteria, as in the toolbar */
142
142
  .AfGrid-headerFilterButton[data-active] {
143
- --dsc-button-color: var(--ds-color-accent-base-default);
144
- --dsc-button-color--hover: var(--ds-color-accent-base-hover);
143
+ --dsc-button-color: var(--ds-color-brand-base-default);
144
+ --dsc-button-color--hover: var(--ds-color-brand-base-hover);
145
145
  }
146
146
 
147
147
  .AfGrid-headerFilterEmpty {
@@ -243,3 +243,9 @@
243
243
  .AfGrid-root .MuiDataGrid-cell a.ds-button {
244
244
  text-decoration: none;
245
245
  }
246
+
247
+ /* Group rows (row grouping): tinted and bold, so the subtotals read apart from the data rows */
248
+ .AfGrid-root .MuiDataGrid-row.AfGrid-groupRow {
249
+ background-color: var(--ds-color-neutral-background-tinted);
250
+ font-weight: 600;
251
+ }
@@ -9,6 +9,9 @@ import {
9
9
  type GridAggregationFunction,
10
10
  type GridApi,
11
11
  type GridFilterModel,
12
+ type GridColSpanFn,
13
+ type GridGroupingColDefOverride,
14
+ type GridGroupingColDefOverrideParams,
12
15
  type GridGroupNode,
13
16
  type GridRowParams,
14
17
  useGridApiRef,
@@ -17,9 +20,10 @@ import { type DataObject, uid } from "@olenbetong/appframe-data";
17
20
  import { DataObjectProvider, useLoading } from "@olenbetong/appframe-react";
18
21
 
19
22
  import clsx from "clsx";
20
- import { useEffect, useMemo, useState } from "react";
23
+ import { useCallback, useEffect, useMemo, useState } from "react";
21
24
  import { FilterBuilder } from "../filter/index.js";
22
25
  import { AfGridColumnsPanel } from "./AfGridColumnsPanel.js";
26
+ import { AfHeaderFilterCell } from "./AfHeaderFilterCell.js";
23
27
  import { type AfGridContextValue, AfGridContextProvider } from "./AfGridContext.js";
24
28
  import { AfGridError } from "./AfGridError.js";
25
29
  import { registerLicense } from "./license.js";
@@ -141,6 +145,58 @@ export {
141
145
  };
142
146
 
143
147
  /** MUI's own default: the grand total in the footer, group subtotals inline. */
148
+ /**
149
+ * On a group row the grouping cell spans the following visible columns up to the first one that
150
+ * shows an aggregate, since those cells are empty there. Data rows span nothing.
151
+ */
152
+ const spanGroupLabel: GridColSpanFn = (_value, row, column, apiRef) => {
153
+ // The callback is typed with the community API; this grid is premium, which has aggregation.
154
+ let api = apiRef.current as GridApi | null;
155
+ if (!api || api.getRowNode(api.getRowId(row))?.type !== "group") return 1;
156
+
157
+ let aggregated = api.state.aggregation?.model ?? {};
158
+ let columns = api.getVisibleColumns();
159
+ let index = columns.findIndex((c) => c.field === column.field);
160
+ let span = 1;
161
+
162
+ while (index + span < columns.length && !aggregated[columns[index + span].field]) {
163
+ span++;
164
+ }
165
+
166
+ return span;
167
+ };
168
+
169
+ /**
170
+ * MUI generates the grouping column itself, so it never passes through `useAfColumns` and got
171
+ * MUI's own header filter. It gets ours instead, filtering on the grouped field when the rows are
172
+ * grouped by a single field, and an empty cell like any unfilterable column otherwise.
173
+ *
174
+ * On group rows the column spans the empty cells after it, so the group label is readable in a
175
+ * column no wider than its expand toggle. A grid can still set its own `colSpan`.
176
+ */
177
+ function getGroupingColDef(
178
+ params: GridGroupingColDefOverrideParams,
179
+ groupingColDef: DataGridProps["groupingColDef"],
180
+ dataObject: DataObject<any>,
181
+ ): GridGroupingColDefOverride {
182
+ let base = typeof groupingColDef === "function" ? groupingColDef(params) : groupingColDef;
183
+ let filterColumn = params.fields.length === 1 ? params.fields[0] : undefined;
184
+
185
+ return {
186
+ ...base,
187
+ colSpan: base?.colSpan ?? spanGroupLabel,
188
+ renderHeaderFilter:
189
+ base?.renderHeaderFilter ??
190
+ ((props) => (
191
+ <AfHeaderFilterCell
192
+ {...props}
193
+ colDef={{ ...props.colDef, filterColumn } as AfGridColDef}
194
+ dataObject={dataObject}
195
+ />
196
+ )),
197
+ };
198
+ }
199
+
144
200
  function getDefaultAggregationPosition(groupNode: GridGroupNode) {
145
201
  return groupNode.depth === -1 ? "footer" : "inline";
146
202
  }
@@ -241,6 +297,12 @@ export type AfGridProps = {
241
297
  * where the client total is wrong.
242
298
  */
243
299
  serverAggregation?: boolean;
300
+ /**
301
+ * Leave out MUI's loading overlay while the data object loads. For a grid that refreshes on a
302
+ * timer: the overlay covers the rows and blocks selecting text in them. The toolbar's refresh
303
+ * button still shows that the grid is loading.
304
+ */
305
+ disableLoadingOverlay?: boolean;
244
306
  } & Omit<
245
307
  DataGridProps,
246
308
  | "apiRef"
@@ -312,18 +374,25 @@ function AfGrid_(props: AfGridProps) {
312
374
  pinnedRows,
313
375
  getRowClassName,
314
376
  serverAggregation = dataObject.options?.dynamicLoading === true,
377
+ disableLoadingOverlay = false,
315
378
  ...other
316
379
  } = props;
317
380
  let apiRefPriv = useGridApiRef();
318
381
  let apiRef = apiRefProp ?? apiRefPriv;
319
382
  useAfGridApi(props, apiRef);
383
+ // Group rows (row grouping) are marked so AfGrid's stylesheet can set them apart from the data rows.
384
+ let getRowClassNameWithGroups = useCallback<NonNullable<DataGridProps["getRowClassName"]>>(
385
+ (params) =>
386
+ clsx(getRowClassName?.(params), apiRef.current?.getRowNode(params.id)?.type === "group" && "AfGrid-groupRow"),
387
+ [getRowClassName, apiRef],
388
+ );
320
389
  let newItemRow = useAfNewItemRow({
321
390
  apiRef,
322
391
  dataObject,
323
392
  position: newItemRowPosition,
324
393
  disableInsert,
325
394
  pinnedRows,
326
- getRowClassName,
395
+ getRowClassName: getRowClassNameWithGroups,
327
396
  });
328
397
  let initialState_ = useAfPersistedState({
329
398
  apiRef,
@@ -431,7 +500,7 @@ function AfGrid_(props: AfGridProps) {
431
500
  apiRef={apiRef}
432
501
  rows={data}
433
502
  columns={columns}
434
- loading={loading}
503
+ loading={!disableLoadingOverlay && loading}
435
504
  getRowId={(row) => row[uid] ?? row[idField]}
436
505
  {...editProps}
437
506
  {...newItemRow.gridProps}
@@ -463,6 +532,7 @@ function AfGrid_(props: AfGridProps) {
463
532
  * so the default position is passed explicitly.
464
533
  */
465
534
  getAggregationPosition={other.getAggregationPosition ?? getDefaultAggregationPosition}
535
+ groupingColDef={(params) => getGroupingColDef(params, other.groupingColDef, dataObject)}
466
536
  localeText={{ ...other.localeText, ...AF_GRID_LOCALE_TEXT }}
467
537
  slots={{
468
538
  ...dsBaseSlots,
@@ -62,6 +62,9 @@ export function useAfGridApi(props: Partial<AfGridProps>, apiRef: React.RefObjec
62
62
  );
63
63
  }
64
64
  apiRef.current?.setPinnedColumns(propsRef.current.initialState?.pinnedColumns ?? {});
65
+ // Grouping and aggregation are part of the layout too: back to what the grid declares.
66
+ apiRef.current?.setRowGroupingModel(propsRef.current.initialState?.rowGrouping?.model ?? []);
67
+ apiRef.current?.setAggregationModel(propsRef.current.initialState?.aggregation?.model ?? {});
65
68
  }, [apiRef]);
66
69
 
67
70
  if (apiRef.current) {
@@ -47,8 +47,12 @@
47
47
  flex-shrink: 0;
48
48
  }
49
49
 
50
+ /*
51
+ * Hover and press tint the item with the text colour, so it darkens the item in light mode and
52
+ * lightens it in dark mode; a black overlay disappeared on the dark menu.
53
+ */
50
54
  .AppMenuItem-root::before {
51
- background-color: #000;
55
+ background-color: var(--ds-color-neutral-text-default, #000);
52
56
  opacity: 0;
53
57
  transition:
54
58
  opacity 30ms linear,
@@ -70,7 +74,7 @@
70
74
  }
71
75
 
72
76
  .AppMenuItem-root:hover::before {
73
- opacity: 0.04;
77
+ opacity: 0.08;
74
78
  }
75
79
 
76
80
  .AppMenuItem-root:active::before {
package/src/mdi/Mdi.css CHANGED
@@ -1,138 +1,138 @@
1
- .ObMdi-root {
2
- position: relative;
3
- width: 100%;
4
- height: 100%;
5
- min-width: 0;
6
- min-height: 0;
7
- }
8
-
9
- .ObMdi-root > .dv-dockview {
10
- width: 100%;
11
- height: 100%;
12
- }
13
-
14
- /*
15
- * The dockview variables mapped to Designsystemet tokens. The theme class is also
16
- * applied to the container in popout windows, so the mapping travels with them.
17
- */
18
- .ObMdi-theme {
19
- --dv-paneview-active-outline-color: var(--ds-color-focus-outer, #1e2b3c);
20
- --dv-tabs-and-actions-container-font-size: var(--ds-font-size-3, 0.875rem);
21
- --dv-tabs-and-actions-container-height: 2.25rem;
22
- --dv-tab-font-size: inherit;
23
- --dv-tabs-and-actions-container-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
24
- --dv-group-view-background-color: var(--ds-color-neutral-background-default, #fff);
25
- --dv-activegroup-visiblepanel-tab-background-color: var(--ds-color-neutral-background-default, #fff);
26
- --dv-activegroup-hiddenpanel-tab-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
27
- --dv-inactivegroup-visiblepanel-tab-background-color: var(--ds-color-neutral-background-tinted, #f8f9fa);
28
- --dv-inactivegroup-hiddenpanel-tab-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
29
- --dv-activegroup-visiblepanel-tab-color: var(--ds-color-neutral-text-default, #292c30);
30
- --dv-activegroup-hiddenpanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
31
- --dv-inactivegroup-visiblepanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
32
- --dv-inactivegroup-hiddenpanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
33
- --dv-tab-divider-color: var(--ds-color-neutral-border-subtle, #d5d7d9);
34
- --dv-separator-border: var(--ds-color-neutral-border-subtle, #d5d7d9);
35
- --dv-paneview-header-border-color: var(--ds-color-neutral-border-default, #a6a9ad);
36
- --dv-sash-color: transparent;
37
- --dv-active-sash-color: var(--ds-color-accent-base-default, #116069);
38
- --dv-active-sash-transition-duration: 0.1s;
39
- --dv-active-sash-transition-delay: 0.3s;
40
- --dv-drag-over-background-color: color-mix(in srgb, var(--ds-color-accent-base-default, #116069) 20%, transparent);
41
- --dv-drag-over-border-color: var(--ds-color-accent-base-default, #116069);
42
- --dv-drag-over-border: none;
43
- --dv-edge-dock-indicator-color: var(--ds-color-accent-base-default, #116069);
44
- --dv-dnd-compass-color: var(--ds-color-neutral-border-default, #a6a9ad);
45
- --dv-dnd-compass-cell-color: var(--ds-color-neutral-surface-default, #f3f4f5);
46
- --dv-dnd-compass-edge-cell-color: var(--ds-color-neutral-surface-hover, #e6e8ea);
47
- --dv-dnd-compass-active-cell-color: var(--ds-color-accent-surface-hover, #d1e5e7);
48
- --dv-tabs-container-scrollbar-color: var(--ds-color-neutral-border-default, #a6a9ad);
49
- --dv-scrollbar-background-color: var(--ds-color-neutral-border-default, #a6a9ad);
50
- --dv-icon-hover-background-color: var(--ds-color-neutral-surface-hover, #e6e8ea);
51
- --dv-context-menu-background-color: var(--ds-color-neutral-background-default, #fff);
52
- --dv-context-menu-color: var(--ds-color-neutral-text-default, #292c30);
53
- --dv-floating-box-shadow: var(--ds-shadow-lg, 0 8px 32px rgba(0, 0, 0, 0.12));
54
- --dv-floating-border: 1px solid var(--ds-color-neutral-border-default, #a6a9ad);
55
- --dv-floating-group-border: none;
56
- --dv-floating-group-dragging-opacity: 0.5;
57
- --dv-floating-titlebar-height: 22px;
58
- --dv-floating-titlebar-background-color: var(--dv-tabs-and-actions-container-background-color);
59
- --dv-floating-titlebar-border-bottom: var(--dv-floating-border);
60
- --dv-overlay-z-index: 999;
61
- --dv-border-radius: 0px;
62
- --dv-tab-margin: 0;
63
- --dv-spacing-padding: 0px;
64
- --dv-tab-border-radius: 0px;
65
- --dv-sash-border-radius: 0px;
66
- --dv-dropdown-border-radius: var(--ds-border-radius-md, 0.25rem);
67
- --dv-tab-close-icon-size: inherit;
68
- --dv-smart-guides-color: var(--ds-color-accent-base-default, #116069);
69
- --dv-smart-guides-preview-color: color-mix(in srgb, var(--ds-color-accent-base-default, #116069) 20%, transparent);
70
- --dv-tab-group-color-grey: #5f6368;
71
- --dv-tab-group-color-blue: #1a73e8;
72
- --dv-tab-group-color-red: #d93025;
73
- --dv-tab-group-color-yellow: #f9ab00;
74
- --dv-tab-group-color-green: #188038;
75
- --dv-tab-group-color-pink: #d01884;
76
- --dv-tab-group-color-purple: #a142f4;
77
- --dv-tab-group-color-cyan: #007b83;
78
- --dv-tab-group-color-orange: #e8710a;
79
- --dv-tab-group-chip-padding: 4px 8px;
80
- --dv-tab-group-chip-border-radius: 6px;
81
- --dv-tab-group-chip-font-size: 11px;
82
- --dv-tab-group-line-height: 2px;
83
- --dv-tab-group-line-opacity: 0.6;
84
-
85
- font-family: var(--ds-font-family, inherit);
86
- color: var(--ds-color-neutral-text-default, #292c30);
87
- }
88
-
89
- /* The active tab gets an accent line so it reads as selected without relying on background alone. */
90
- .ObMdi-theme .dv-tab.dv-active-tab {
91
- box-shadow: inset 0 -2px 0 var(--ds-color-accent-base-default, #116069);
92
- }
93
-
94
- .ObMdi-theme .dv-tab:focus-visible {
95
- outline: 2px solid var(--ds-color-focus-outer, #1e2b3c);
96
- outline-offset: -2px;
97
- }
98
-
99
- /* Dirty marker: a dot after the title */
100
- .ObMdi-tab--dirty .dv-default-tab-content::after {
101
- content: " \2022";
102
- color: var(--ds-color-warning-base-default, #b8860b);
103
- }
104
-
105
- .ObMdi-error {
106
- display: flex;
107
- flex-direction: column;
108
- gap: var(--ds-size-2, 0.5rem);
109
- padding: var(--ds-size-4, 1rem);
110
- color: var(--ds-color-danger-text-default, #b3221a);
111
- }
112
-
113
- .ObMdi-error-title {
114
- margin: 0;
115
- font-weight: 600;
116
- }
117
-
118
- .ObMdi-error-message {
119
- margin: 0;
120
- white-space: pre-wrap;
121
- font-size: var(--ds-font-size-2, 0.8125rem);
122
- color: var(--ds-color-neutral-text-subtle, #5b5f64);
123
- }
124
-
125
- .ObMdi-watermark {
126
- display: flex;
127
- align-items: center;
128
- justify-content: center;
129
- width: 100%;
130
- height: 100%;
131
- color: var(--ds-color-neutral-text-subtle, #5b5f64);
132
- }
133
-
134
- .ObMdi-confirmClose-actions {
135
- display: flex;
136
- gap: var(--ds-size-2, 0.5rem);
137
- justify-content: flex-end;
138
- }
1
+ .ObMdi-root {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ min-width: 0;
6
+ min-height: 0;
7
+ }
8
+
9
+ .ObMdi-root > .dv-dockview {
10
+ width: 100%;
11
+ height: 100%;
12
+ }
13
+
14
+ /*
15
+ * The dockview variables mapped to Designsystemet tokens. The theme class is also
16
+ * applied to the container in popout windows, so the mapping travels with them.
17
+ */
18
+ .ObMdi-theme {
19
+ --dv-paneview-active-outline-color: var(--ds-color-focus-outer, #1e2b3c);
20
+ --dv-tabs-and-actions-container-font-size: var(--ds-font-size-3, 0.875rem);
21
+ --dv-tabs-and-actions-container-height: 2.25rem;
22
+ --dv-tab-font-size: inherit;
23
+ --dv-tabs-and-actions-container-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
24
+ --dv-group-view-background-color: var(--ds-color-neutral-background-default, #fff);
25
+ --dv-activegroup-visiblepanel-tab-background-color: var(--ds-color-neutral-background-default, #fff);
26
+ --dv-activegroup-hiddenpanel-tab-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
27
+ --dv-inactivegroup-visiblepanel-tab-background-color: var(--ds-color-neutral-background-tinted, #f8f9fa);
28
+ --dv-inactivegroup-hiddenpanel-tab-background-color: var(--ds-color-neutral-surface-default, #f3f4f5);
29
+ --dv-activegroup-visiblepanel-tab-color: var(--ds-color-neutral-text-default, #292c30);
30
+ --dv-activegroup-hiddenpanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
31
+ --dv-inactivegroup-visiblepanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
32
+ --dv-inactivegroup-hiddenpanel-tab-color: var(--ds-color-neutral-text-subtle, #5b5f64);
33
+ --dv-tab-divider-color: var(--ds-color-neutral-border-subtle, #d5d7d9);
34
+ --dv-separator-border: var(--ds-color-neutral-border-subtle, #d5d7d9);
35
+ --dv-paneview-header-border-color: var(--ds-color-neutral-border-default, #a6a9ad);
36
+ --dv-sash-color: transparent;
37
+ --dv-active-sash-color: var(--ds-color-brand-base-default, #116069);
38
+ --dv-active-sash-transition-duration: 0.1s;
39
+ --dv-active-sash-transition-delay: 0.3s;
40
+ --dv-drag-over-background-color: color-mix(in srgb, var(--ds-color-brand-base-default, #116069) 20%, transparent);
41
+ --dv-drag-over-border-color: var(--ds-color-brand-base-default, #116069);
42
+ --dv-drag-over-border: none;
43
+ --dv-edge-dock-indicator-color: var(--ds-color-brand-base-default, #116069);
44
+ --dv-dnd-compass-color: var(--ds-color-neutral-border-default, #a6a9ad);
45
+ --dv-dnd-compass-cell-color: var(--ds-color-neutral-surface-default, #f3f4f5);
46
+ --dv-dnd-compass-edge-cell-color: var(--ds-color-neutral-surface-hover, #e6e8ea);
47
+ --dv-dnd-compass-active-cell-color: var(--ds-color-brand-surface-hover, #d1e5e7);
48
+ --dv-tabs-container-scrollbar-color: var(--ds-color-neutral-border-default, #a6a9ad);
49
+ --dv-scrollbar-background-color: var(--ds-color-neutral-border-default, #a6a9ad);
50
+ --dv-icon-hover-background-color: var(--ds-color-neutral-surface-hover, #e6e8ea);
51
+ --dv-context-menu-background-color: var(--ds-color-neutral-background-default, #fff);
52
+ --dv-context-menu-color: var(--ds-color-neutral-text-default, #292c30);
53
+ --dv-floating-box-shadow: var(--ds-shadow-lg, 0 8px 32px rgba(0, 0, 0, 0.12));
54
+ --dv-floating-border: 1px solid var(--ds-color-neutral-border-default, #a6a9ad);
55
+ --dv-floating-group-border: none;
56
+ --dv-floating-group-dragging-opacity: 0.5;
57
+ --dv-floating-titlebar-height: 22px;
58
+ --dv-floating-titlebar-background-color: var(--dv-tabs-and-actions-container-background-color);
59
+ --dv-floating-titlebar-border-bottom: var(--dv-floating-border);
60
+ --dv-overlay-z-index: 999;
61
+ --dv-border-radius: 0px;
62
+ --dv-tab-margin: 0;
63
+ --dv-spacing-padding: 0px;
64
+ --dv-tab-border-radius: 0px;
65
+ --dv-sash-border-radius: 0px;
66
+ --dv-dropdown-border-radius: var(--ds-border-radius-md, 0.25rem);
67
+ --dv-tab-close-icon-size: inherit;
68
+ --dv-smart-guides-color: var(--ds-color-brand-base-default, #116069);
69
+ --dv-smart-guides-preview-color: color-mix(in srgb, var(--ds-color-brand-base-default, #116069) 20%, transparent);
70
+ --dv-tab-group-color-grey: #5f6368;
71
+ --dv-tab-group-color-blue: #1a73e8;
72
+ --dv-tab-group-color-red: #d93025;
73
+ --dv-tab-group-color-yellow: #f9ab00;
74
+ --dv-tab-group-color-green: #188038;
75
+ --dv-tab-group-color-pink: #d01884;
76
+ --dv-tab-group-color-purple: #a142f4;
77
+ --dv-tab-group-color-cyan: #007b83;
78
+ --dv-tab-group-color-orange: #e8710a;
79
+ --dv-tab-group-chip-padding: 4px 8px;
80
+ --dv-tab-group-chip-border-radius: 6px;
81
+ --dv-tab-group-chip-font-size: 11px;
82
+ --dv-tab-group-line-height: 2px;
83
+ --dv-tab-group-line-opacity: 0.6;
84
+
85
+ font-family: var(--ds-font-family, inherit);
86
+ color: var(--ds-color-neutral-text-default, #292c30);
87
+ }
88
+
89
+ /* The active tab gets an accent line so it reads as selected without relying on background alone. */
90
+ .ObMdi-theme .dv-tab.dv-active-tab {
91
+ box-shadow: inset 0 -2px 0 var(--ds-color-brand-base-default, #116069);
92
+ }
93
+
94
+ .ObMdi-theme .dv-tab:focus-visible {
95
+ outline: 2px solid var(--ds-color-focus-outer, #1e2b3c);
96
+ outline-offset: -2px;
97
+ }
98
+
99
+ /* Dirty marker: a dot after the title */
100
+ .ObMdi-tab--dirty .dv-default-tab-content::after {
101
+ content: " \2022";
102
+ color: var(--ds-color-warning-base-default, #b8860b);
103
+ }
104
+
105
+ .ObMdi-error {
106
+ display: flex;
107
+ flex-direction: column;
108
+ gap: var(--ds-size-2, 0.5rem);
109
+ padding: var(--ds-size-4, 1rem);
110
+ color: var(--ds-color-danger-text-default, #b3221a);
111
+ }
112
+
113
+ .ObMdi-error-title {
114
+ margin: 0;
115
+ font-weight: 600;
116
+ }
117
+
118
+ .ObMdi-error-message {
119
+ margin: 0;
120
+ white-space: pre-wrap;
121
+ font-size: var(--ds-font-size-2, 0.8125rem);
122
+ color: var(--ds-color-neutral-text-subtle, #5b5f64);
123
+ }
124
+
125
+ .ObMdi-watermark {
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ width: 100%;
130
+ height: 100%;
131
+ color: var(--ds-color-neutral-text-subtle, #5b5f64);
132
+ }
133
+
134
+ .ObMdi-confirmClose-actions {
135
+ display: flex;
136
+ gap: var(--ds-size-2, 0.5rem);
137
+ justify-content: flex-end;
138
+ }