@olenbetong/appframe-ds 1.0.3 → 1.2.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 +13 -0
- package/package.json +8 -7
- package/scripts/copyAssets.mjs +27 -55
- package/src/AfLookup/Lookup.css +129 -125
- package/src/AfLookup/Lookup.tsx +184 -162
- package/src/AfLookup/LookupCombobox.css +78 -78
- package/src/AfLookup/LookupCombobox.tsx +237 -237
- package/src/AfLookup/LookupEdit.tsx +130 -130
- package/src/AfLookup/LookupGrid.tsx +124 -124
- package/src/AfLookup/index.ts +5 -5
- package/src/autocomplete/Autocomplete.css +256 -256
- package/src/autocomplete/Autocomplete.tsx +320 -320
- package/src/autocomplete/AutocompleteFrame.tsx +168 -168
- package/src/autocomplete/Combobox.tsx +286 -286
- package/src/autocomplete/index.ts +4 -4
- package/src/autocomplete/types.ts +204 -204
- package/src/autocomplete/utils.ts +183 -183
- package/src/binding/BoundNumericTextField.tsx +102 -102
- package/src/binding/BoundTextField.tsx +49 -49
- package/src/binding/CancelButton.tsx +30 -30
- package/src/binding/CancelIconButton.tsx +30 -30
- package/src/binding/DataEditToolbar.tsx +92 -92
- package/src/binding/DeleteButton.tsx +35 -35
- package/src/binding/DeleteIconButton.tsx +35 -35
- package/src/binding/RefreshButton.tsx +31 -31
- package/src/binding/RefreshIconButton.tsx +33 -33
- package/src/binding/RefreshRowIconButton.tsx +33 -33
- package/src/binding/SaveButton.tsx +37 -37
- package/src/binding/SaveIconButton.tsx +38 -38
- package/src/container/Container.tsx +49 -49
- package/src/container/index.ts +1 -1
- package/src/cutoff/CutOffPicker.css +12 -0
- package/src/cutoff/CutOffPicker.tsx +165 -0
- package/src/cutoff/context.tsx +194 -0
- package/src/cutoff/dsCutOffDates.ts +21 -0
- package/src/cutoff/index.ts +4 -0
- package/src/cutoff/utils.test.ts +59 -0
- package/src/cutoff/utils.ts +276 -0
- package/src/filter/ChipListInput.tsx +79 -79
- package/src/filter/FieldFilterPanel.css +150 -150
- package/src/filter/FieldFilterPanel.tsx +309 -309
- package/src/filter/FilterBuilder.css +152 -152
- package/src/filter/FilterBuilder.test.tsx +153 -153
- package/src/filter/FilterBuilder.tsx +435 -435
- package/src/filter/FilterEditor.css +231 -231
- package/src/filter/FilterEditor.test.tsx +259 -259
- package/src/filter/FilterEditor.tsx +75 -74
- package/src/filter/FilterGroupEditor.tsx +160 -160
- package/src/filter/FilterNameDialog.css +22 -22
- package/src/filter/FilterNameDialog.tsx +81 -81
- package/src/filter/FilterRow.tsx +117 -117
- package/src/filter/FilterShareDialog.css +28 -28
- package/src/filter/FilterShareDialog.tsx +201 -201
- package/src/filter/FilterStringField.tsx +78 -77
- package/src/filter/FilterValueEditor.tsx +220 -220
- package/src/filter/SavedFilterTree.css +107 -107
- package/src/filter/SavedFilterTree.test.tsx +94 -94
- package/src/filter/SavedFilterTree.tsx +218 -222
- package/src/filter/fieldFilter.test.ts +158 -158
- package/src/filter/fieldFilter.ts +139 -139
- package/src/filter/index.ts +27 -27
- package/src/filter/types.ts +38 -38
- package/src/filter/useDistinctValues.test.ts +102 -102
- package/src/filter/useDistinctValues.ts +230 -230
- package/src/global.d.ts +11 -11
- package/src/grid/AfGridColumnsPanel.tsx +118 -118
- package/src/grid/AfGridContext.tsx +51 -51
- package/src/grid/AfGridError.tsx +46 -46
- package/src/grid/AfHeaderFilterCell.tsx +147 -151
- package/src/grid/AfHeaderFilterPanel.tsx +111 -111
- package/src/grid/GridEditLookup.css +12 -0
- package/src/grid/GridEditLookup.tsx +121 -0
- package/src/grid/Toolbar.tsx +233 -233
- package/src/grid/editing.ts +100 -100
- package/src/grid/filter.ts +78 -78
- package/src/grid/formatters.ts +48 -48
- package/src/grid/index.css +245 -245
- package/src/grid/index.tsx +489 -484
- package/src/grid/license.ts +48 -48
- package/src/grid/localization.ts +369 -369
- package/src/grid/slots/index.tsx +307 -307
- package/src/grid/slots/slots.css +64 -64
- package/src/grid/theme.tsx +138 -138
- package/src/grid/useAfColumns.tsx +371 -371
- package/src/grid/useAfCurrentIndex.ts +63 -63
- package/src/grid/useAfData.ts +20 -20
- package/src/grid/useAfFilter.ts +160 -160
- package/src/grid/useAfFilterFields.ts +55 -55
- package/src/grid/useAfGridApi.ts +71 -71
- package/src/grid/useAfKeyBindings.ts +36 -36
- package/src/grid/useAfNewItemRow.ts +258 -258
- package/src/grid/useAfPagination.ts +53 -53
- package/src/grid/useAfPersistedState.ts +230 -230
- package/src/grid/useAfRowEditModel.ts +145 -145
- package/src/grid/useAfRowGrouping.ts +47 -47
- package/src/grid/useAfServerAggregation.ts +145 -145
- package/src/grid/useAfSortModel.ts +84 -84
- package/src/i18n.ts +13 -0
- package/src/index.ts +14 -12
- package/src/input/InputAdornments.css +75 -75
- package/src/input/InputAdornments.tsx +102 -102
- package/src/input/index.ts +1 -1
- package/src/layout/AppMenu.tsx +74 -75
- package/src/layout/AppMenuDrawer.css +70 -70
- package/src/layout/AppMenuDrawer.tsx +122 -122
- package/src/layout/ErrorBoundary.tsx +162 -162
- package/src/layout/ResponsiveDialog.css +86 -0
- package/src/layout/ResponsiveDialog.tsx +55 -0
- package/src/layout/index.tsx +69 -68
- package/src/link/Link.tsx +23 -0
- package/src/link/index.ts +1 -0
- package/src/mdi/Mdi.css +138 -138
- package/src/mdi/Mdi.test.tsx +91 -87
- package/src/mdi/Mdi.tsx +141 -141
- package/src/mdi/MdiConfirmCloseDialog.tsx +47 -47
- package/src/mdi/MdiContext.tsx +59 -59
- package/src/mdi/MdiDocumentContext.tsx +60 -60
- package/src/mdi/MdiPanel.tsx +61 -61
- package/src/mdi/MdiRestore.test.tsx +86 -82
- package/src/mdi/MdiTab.tsx +30 -30
- package/src/mdi/controller.test.ts +382 -382
- package/src/mdi/controller.ts +656 -656
- package/src/mdi/dockviewHost.ts +132 -132
- package/src/mdi/fakeHost.ts +200 -200
- package/src/mdi/host.ts +44 -44
- package/src/mdi/ids.test.ts +20 -20
- package/src/mdi/ids.ts +18 -18
- package/src/mdi/index.ts +31 -31
- package/src/mdi/layoutRestore.test.ts +156 -156
- package/src/mdi/layoutRestore.ts +311 -311
- package/src/mdi/layoutSpec.test.ts +143 -143
- package/src/mdi/layoutSpec.ts +214 -214
- package/src/mdi/layoutStore.test.ts +93 -93
- package/src/mdi/layoutStore.ts +99 -99
- package/src/mdi/memorySettingsStore.ts +21 -21
- package/src/mdi/registry.ts +34 -34
- package/src/mdi/testTypes.ts +37 -37
- package/src/mdi/theme.ts +22 -22
- package/src/mdi/types.ts +214 -214
- package/src/page/Page.css +53 -53
- package/src/page/PageBlock.css +64 -64
- package/src/page/PageBlock.tsx +92 -92
- package/src/page/PageHeader.css +88 -88
- package/src/page/PageHeader.tsx +115 -116
- package/src/page/PageTitle.css +5 -0
- package/src/page/PageTitle.tsx +21 -0
- package/src/page/index.ts +4 -3
- package/src/paper/Paper.tsx +52 -52
- package/src/progress/LinearProgress.css +93 -93
- package/src/progress/LinearProgress.tsx +104 -104
- package/src/progress/index.ts +1 -1
- package/src/report-downloader/ReportDownloader.css +67 -67
- package/src/report-downloader/components/StatusItem.tsx +87 -86
- package/src/report-downloader/components/StatusList.tsx +28 -28
- package/src/report-downloader/index.ts +41 -41
- package/src/report-downloader/status.tsx +92 -92
- package/src/sortable/DropIndicator.css +51 -51
- package/src/sortable/DropIndicator.tsx +27 -27
- package/src/sortable/SortableItemList.css +21 -21
- package/src/sortable/SortableItemList.tsx +264 -264
- package/src/sortable/index.ts +8 -8
- package/src/sortable/reorderSortOrder.ts +126 -126
- package/src/sortable/sortOrder.ts +101 -101
- package/src/sortable/types.ts +9 -9
- package/src/sortable/useSortableContainer.ts +53 -53
- package/src/sortable/useSortableItem.ts +95 -95
- package/src/sortable/useSortableList.ts +117 -117
- package/src/test/happy-dom-document-class.ts +24 -24
- package/src/test/setup.ts +12 -12
- package/src/theme/useDsColorScheme.ts +53 -53
- package/tsconfig.build.json +9 -9
- package/tsconfig.json +8 -8
- package/vitest.config.ts +10 -10
package/src/page/PageBlock.tsx
CHANGED
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
import "./PageBlock.css";
|
|
2
|
-
|
|
3
|
-
import clsx from "clsx";
|
|
4
|
-
import type React from "react";
|
|
5
|
-
|
|
6
|
-
export const pageBlockWidths = ["text", "md", "lg", "xl", "2xl"] as const;
|
|
7
|
-
|
|
8
|
-
export type PageBlockWidth = (typeof pageBlockWidths)[number];
|
|
9
|
-
|
|
10
|
-
export type PageBlockProps = React.HTMLAttributes<HTMLElement> & {
|
|
11
|
-
/**
|
|
12
|
-
* Where a width-constrained block sits in the space available to it.
|
|
13
|
-
*
|
|
14
|
-
* `center` is the MUI `Container` behaviour. `start` keeps the content against the leading
|
|
15
|
-
* edge, which is what the old `PageContainer` did (it forced `margin-left: 0`) and what an app
|
|
16
|
-
* with a docked navigation drawer usually wants — centering leaves the content floating away
|
|
17
|
-
* from the menu it belongs to.
|
|
18
|
-
*
|
|
19
|
-
* Has no effect without a `width`, since the block already fills its parent.
|
|
20
|
-
* @default "center"
|
|
21
|
-
*/
|
|
22
|
-
align?: "center" | "start";
|
|
23
|
-
/**
|
|
24
|
-
* Overrides the rendered element (e.g. `"main"`, `"header"`, `"footer"`)
|
|
25
|
-
* @default "div"
|
|
26
|
-
*/
|
|
27
|
-
as?: React.ElementType;
|
|
28
|
-
children?: React.ReactNode;
|
|
29
|
-
/**
|
|
30
|
-
* Fills the remaining space of the parent `Page`. Combine with
|
|
31
|
-
* `overflow="auto"` inside `<Page layout="app">` to make the block the
|
|
32
|
-
* scroll container.
|
|
33
|
-
* @default false
|
|
34
|
-
*/
|
|
35
|
-
grow?: boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Adds a standardised responsive inline padding
|
|
38
|
-
* @default false
|
|
39
|
-
*/
|
|
40
|
-
gutters?: boolean;
|
|
41
|
-
/**
|
|
42
|
-
* Overflow behaviour of the block. Only relevant inside
|
|
43
|
-
* `<Page layout="app">`, where scrolling is delegated down the tree.
|
|
44
|
-
*/
|
|
45
|
-
overflow?: "auto" | "hidden";
|
|
46
|
-
/**
|
|
47
|
-
* Predefined max-width. Content is horizontally centered.
|
|
48
|
-
*
|
|
49
|
-
* - `text`: 36rem (576px) — recommended line-length for running text
|
|
50
|
-
* - `md`: 48rem (768px)
|
|
51
|
-
* - `lg`: 64rem (1024px)
|
|
52
|
-
* - `xl`: 80rem (1280px)
|
|
53
|
-
* - `2xl`: 90rem (1440px)
|
|
54
|
-
*
|
|
55
|
-
* @default max-width: 100%
|
|
56
|
-
*/
|
|
57
|
-
width?: PageBlockWidth;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Layout block for defining max-width, gutters and horizontal centering.
|
|
62
|
-
* Replaces the deprecated `PageContainer` (`maxWidth` mapping: `xs`/`sm` →
|
|
63
|
-
* `text`, `md` → `md`, `lg` → `lg`, `xl` → `xl`, `false` → no `width`).
|
|
64
|
-
*/
|
|
65
|
-
export function PageBlock({
|
|
66
|
-
align,
|
|
67
|
-
as: Component = "div",
|
|
68
|
-
children,
|
|
69
|
-
className,
|
|
70
|
-
grow,
|
|
71
|
-
gutters,
|
|
72
|
-
overflow,
|
|
73
|
-
width,
|
|
74
|
-
...props
|
|
75
|
-
}: PageBlockProps) {
|
|
76
|
-
return (
|
|
77
|
-
<Component
|
|
78
|
-
className={clsx(
|
|
79
|
-
"ObPageBlock-root",
|
|
80
|
-
width && `ObPageBlock-${width}`,
|
|
81
|
-
align === "start" && "ObPageBlock-alignStart",
|
|
82
|
-
gutters && "ObPageBlock-gutters",
|
|
83
|
-
grow && "ObPageBlock-grow",
|
|
84
|
-
overflow && `ObPageBlock-overflow${overflow === "auto" ? "Auto" : "Hidden"}`,
|
|
85
|
-
className,
|
|
86
|
-
)}
|
|
87
|
-
{...props}
|
|
88
|
-
>
|
|
89
|
-
{children}
|
|
90
|
-
</Component>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
1
|
+
import "./PageBlock.css";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import type React from "react";
|
|
5
|
+
|
|
6
|
+
export const pageBlockWidths = ["text", "md", "lg", "xl", "2xl"] as const;
|
|
7
|
+
|
|
8
|
+
export type PageBlockWidth = (typeof pageBlockWidths)[number];
|
|
9
|
+
|
|
10
|
+
export type PageBlockProps = React.HTMLAttributes<HTMLElement> & {
|
|
11
|
+
/**
|
|
12
|
+
* Where a width-constrained block sits in the space available to it.
|
|
13
|
+
*
|
|
14
|
+
* `center` is the MUI `Container` behaviour. `start` keeps the content against the leading
|
|
15
|
+
* edge, which is what the old `PageContainer` did (it forced `margin-left: 0`) and what an app
|
|
16
|
+
* with a docked navigation drawer usually wants — centering leaves the content floating away
|
|
17
|
+
* from the menu it belongs to.
|
|
18
|
+
*
|
|
19
|
+
* Has no effect without a `width`, since the block already fills its parent.
|
|
20
|
+
* @default "center"
|
|
21
|
+
*/
|
|
22
|
+
align?: "center" | "start";
|
|
23
|
+
/**
|
|
24
|
+
* Overrides the rendered element (e.g. `"main"`, `"header"`, `"footer"`)
|
|
25
|
+
* @default "div"
|
|
26
|
+
*/
|
|
27
|
+
as?: React.ElementType;
|
|
28
|
+
children?: React.ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Fills the remaining space of the parent `Page`. Combine with
|
|
31
|
+
* `overflow="auto"` inside `<Page layout="app">` to make the block the
|
|
32
|
+
* scroll container.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
grow?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Adds a standardised responsive inline padding
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
gutters?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Overflow behaviour of the block. Only relevant inside
|
|
43
|
+
* `<Page layout="app">`, where scrolling is delegated down the tree.
|
|
44
|
+
*/
|
|
45
|
+
overflow?: "auto" | "hidden";
|
|
46
|
+
/**
|
|
47
|
+
* Predefined max-width. Content is horizontally centered.
|
|
48
|
+
*
|
|
49
|
+
* - `text`: 36rem (576px) — recommended line-length for running text
|
|
50
|
+
* - `md`: 48rem (768px)
|
|
51
|
+
* - `lg`: 64rem (1024px)
|
|
52
|
+
* - `xl`: 80rem (1280px)
|
|
53
|
+
* - `2xl`: 90rem (1440px)
|
|
54
|
+
*
|
|
55
|
+
* @default max-width: 100%
|
|
56
|
+
*/
|
|
57
|
+
width?: PageBlockWidth;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Layout block for defining max-width, gutters and horizontal centering.
|
|
62
|
+
* Replaces the deprecated `PageContainer` (`maxWidth` mapping: `xs`/`sm` →
|
|
63
|
+
* `text`, `md` → `md`, `lg` → `lg`, `xl` → `xl`, `false` → no `width`).
|
|
64
|
+
*/
|
|
65
|
+
export function PageBlock({
|
|
66
|
+
align,
|
|
67
|
+
as: Component = "div",
|
|
68
|
+
children,
|
|
69
|
+
className,
|
|
70
|
+
grow,
|
|
71
|
+
gutters,
|
|
72
|
+
overflow,
|
|
73
|
+
width,
|
|
74
|
+
...props
|
|
75
|
+
}: PageBlockProps) {
|
|
76
|
+
return (
|
|
77
|
+
<Component
|
|
78
|
+
className={clsx(
|
|
79
|
+
"ObPageBlock-root",
|
|
80
|
+
width && `ObPageBlock-${width}`,
|
|
81
|
+
align === "start" && "ObPageBlock-alignStart",
|
|
82
|
+
gutters && "ObPageBlock-gutters",
|
|
83
|
+
grow && "ObPageBlock-grow",
|
|
84
|
+
overflow && `ObPageBlock-overflow${overflow === "auto" ? "Auto" : "Hidden"}`,
|
|
85
|
+
className,
|
|
86
|
+
)}
|
|
87
|
+
{...props}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</Component>
|
|
91
|
+
);
|
|
92
|
+
}
|
package/src/page/PageHeader.css
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
.ObPageHeader-root {
|
|
2
|
-
flex: 0 0 auto;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
/* --- appbar variant --- */
|
|
6
|
-
|
|
7
|
-
.ObPageHeader-appbar {
|
|
8
|
-
background-color: var(--ds-color-brand-base-default, #0062ba);
|
|
9
|
-
color: var(--ds-color-brand-base-contrast-default, #fff);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.ObPageHeader-appbar .ObPageHeader-bar {
|
|
13
|
-
display: flex;
|
|
14
|
-
align-items: center;
|
|
15
|
-
gap: 0.5rem;
|
|
16
|
-
min-height: var(--ob-page-appbar-height, 3.5rem);
|
|
17
|
-
padding-inline: 0.5rem 1rem;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.ObPageHeader-title {
|
|
21
|
-
flex: 1 1 auto;
|
|
22
|
-
margin: 0;
|
|
23
|
-
font-size: var(--ds-font-size-lg, 1.25rem);
|
|
24
|
-
font-weight: 500;
|
|
25
|
-
overflow: hidden;
|
|
26
|
-
text-overflow: ellipsis;
|
|
27
|
-
white-space: nowrap;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.ObPageHeader-actions {
|
|
31
|
-
display: flex;
|
|
32
|
-
align-items: center;
|
|
33
|
-
gap: 0.5rem;
|
|
34
|
-
margin-left: auto;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.ObPageHeader-title + .ObPageHeader-actions {
|
|
38
|
-
margin-left: 0;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.ObPageHeader-toggle {
|
|
42
|
-
display: flex;
|
|
43
|
-
align-items: center;
|
|
44
|
-
justify-content: center;
|
|
45
|
-
background: transparent;
|
|
46
|
-
border: none;
|
|
47
|
-
color: inherit;
|
|
48
|
-
cursor: pointer;
|
|
49
|
-
border-radius: 50%;
|
|
50
|
-
height: 2.75rem;
|
|
51
|
-
width: 2.75rem;
|
|
52
|
-
font-size: 1.5rem;
|
|
53
|
-
flex-shrink: 0;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.ObPageHeader-toggle:hover {
|
|
57
|
-
background-color: rgb(255 255 255 / 0.12);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* --- plain variant --- */
|
|
61
|
-
|
|
62
|
-
.ObPageHeader-plainInner {
|
|
63
|
-
display: flex;
|
|
64
|
-
align-items: center;
|
|
65
|
-
gap: 0.5rem;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.ObPageHeader-plainTitle {
|
|
69
|
-
margin: 0;
|
|
70
|
-
font-size: var(--ds-font-size-xl, 1.5rem);
|
|
71
|
-
font-weight: 500;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/*
|
|
75
|
-
* Reserved slot for the app-launcher and user profile menu in the future
|
|
76
|
-
* sidebar-free site layout. Hidden under the current sidebar layout; the
|
|
77
|
-
* activation mechanism is decided together with the new website template.
|
|
78
|
-
*/
|
|
79
|
-
.ObPageHeader-end {
|
|
80
|
-
display: none;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
@media print {
|
|
84
|
-
.ObPageHeader-appbar .ObPageHeader-bar,
|
|
85
|
-
.ObPageHeader-toggle {
|
|
86
|
-
display: none !important;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
1
|
+
.ObPageHeader-root {
|
|
2
|
+
flex: 0 0 auto;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* --- appbar variant --- */
|
|
6
|
+
|
|
7
|
+
.ObPageHeader-appbar {
|
|
8
|
+
background-color: var(--ds-color-brand-base-default, #0062ba);
|
|
9
|
+
color: var(--ds-color-brand-base-contrast-default, #fff);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ObPageHeader-appbar .ObPageHeader-bar {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 0.5rem;
|
|
16
|
+
min-height: var(--ob-page-appbar-height, 3.5rem);
|
|
17
|
+
padding-inline: 0.5rem 1rem;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ObPageHeader-title {
|
|
21
|
+
flex: 1 1 auto;
|
|
22
|
+
margin: 0;
|
|
23
|
+
font-size: var(--ds-font-size-lg, 1.25rem);
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
text-overflow: ellipsis;
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ObPageHeader-actions {
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 0.5rem;
|
|
34
|
+
margin-left: auto;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.ObPageHeader-title + .ObPageHeader-actions {
|
|
38
|
+
margin-left: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.ObPageHeader-toggle {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
background: transparent;
|
|
46
|
+
border: none;
|
|
47
|
+
color: inherit;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
height: 2.75rem;
|
|
51
|
+
width: 2.75rem;
|
|
52
|
+
font-size: 1.5rem;
|
|
53
|
+
flex-shrink: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ObPageHeader-toggle:hover {
|
|
57
|
+
background-color: rgb(255 255 255 / 0.12);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* --- plain variant --- */
|
|
61
|
+
|
|
62
|
+
.ObPageHeader-plainInner {
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 0.5rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.ObPageHeader-plainTitle {
|
|
69
|
+
margin: 0;
|
|
70
|
+
font-size: var(--ds-font-size-xl, 1.5rem);
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
* Reserved slot for the app-launcher and user profile menu in the future
|
|
76
|
+
* sidebar-free site layout. Hidden under the current sidebar layout; the
|
|
77
|
+
* activation mechanism is decided together with the new website template.
|
|
78
|
+
*/
|
|
79
|
+
.ObPageHeader-end {
|
|
80
|
+
display: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@media print {
|
|
84
|
+
.ObPageHeader-appbar .ObPageHeader-bar,
|
|
85
|
+
.ObPageHeader-toggle {
|
|
86
|
+
display: none !important;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/page/PageHeader.tsx
CHANGED
|
@@ -1,116 +1,115 @@
|
|
|
1
|
-
import "./PageHeader.css";
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import type
|
|
7
|
-
|
|
8
|
-
import { type
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* -
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
aria-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
{
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
1
|
+
import "./PageHeader.css";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import type React from "react";
|
|
5
|
+
|
|
6
|
+
import { type AppMenuProps } from "../layout/AppMenu.js";
|
|
7
|
+
import { AppMenuDrawer, useAppMenuDrawer } from "../layout/AppMenuDrawer.js";
|
|
8
|
+
import { PageBlock, type PageBlockWidth } from "./PageBlock.js";
|
|
9
|
+
import { getLocalizedString } from "../i18n.js";
|
|
10
|
+
|
|
11
|
+
export type PageHeaderVariant = "appbar" | "plain";
|
|
12
|
+
|
|
13
|
+
export type PageHeaderProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
|
|
14
|
+
/**
|
|
15
|
+
* Actions displayed at the end of the header (buttons, search, etc.)
|
|
16
|
+
*/
|
|
17
|
+
actions?: React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Props passed to the `AppMenu` wrapping the `menu` content
|
|
20
|
+
*/
|
|
21
|
+
AppMenuProps?: AppMenuProps;
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* App menu (navigation) content. When provided, the `appbar` variant
|
|
25
|
+
* renders a menu toggle button and a drawer hosting the menu — docked on
|
|
26
|
+
* desktop (≥1200px), overlay on smaller screens.
|
|
27
|
+
*/
|
|
28
|
+
menu?: React.ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Application title
|
|
31
|
+
*/
|
|
32
|
+
title?: React.ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Adds a standardised responsive inline padding to the header content.
|
|
35
|
+
* See `Page.Block`.
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
gutters?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Constrains and centers the header content to a predefined max-width,
|
|
41
|
+
* so it can align with a `Page.Block` of the same width. See `Page.Block`.
|
|
42
|
+
*/
|
|
43
|
+
width?: PageBlockWidth;
|
|
44
|
+
/**
|
|
45
|
+
* - `"appbar"` (default): a top app bar with menu toggle, title and
|
|
46
|
+
* actions. For apps that have an app menu.
|
|
47
|
+
* - `"plain"`: no app bar chrome — for simple apps without an app menu
|
|
48
|
+
* (e.g. report-issue). Renders the title as a regular heading block.
|
|
49
|
+
*
|
|
50
|
+
* Both variants reserve an end-slot (`.ObPageHeader-end`) that will host
|
|
51
|
+
* the app-launcher and user profile menu in the future sidebar-free site
|
|
52
|
+
* layout. It is hidden under the current sidebar layout.
|
|
53
|
+
* @default "appbar"
|
|
54
|
+
*/
|
|
55
|
+
variant?: PageHeaderVariant;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Page header for use inside `Page`. See the `variant` prop for the two
|
|
60
|
+
* supported header styles.
|
|
61
|
+
*/
|
|
62
|
+
export function PageHeader({
|
|
63
|
+
actions,
|
|
64
|
+
AppMenuProps,
|
|
65
|
+
children,
|
|
66
|
+
className,
|
|
67
|
+
gutters,
|
|
68
|
+
menu,
|
|
69
|
+
title,
|
|
70
|
+
variant = "appbar",
|
|
71
|
+
width,
|
|
72
|
+
...props
|
|
73
|
+
}: PageHeaderProps) {
|
|
74
|
+
let { open, isMobile, toggle, close } = useAppMenuDrawer();
|
|
75
|
+
|
|
76
|
+
if (variant === "plain") {
|
|
77
|
+
return (
|
|
78
|
+
<header className={clsx("ObPageHeader-root", "ObPageHeader-plain", className)} {...props}>
|
|
79
|
+
<PageBlock className="ObPageHeader-plainInner" width={width} gutters={gutters}>
|
|
80
|
+
{title && <h1 className="ObPageHeader-plainTitle">{title}</h1>}
|
|
81
|
+
{actions && <div className="ObPageHeader-actions">{actions}</div>}
|
|
82
|
+
{children}
|
|
83
|
+
<div className="ObPageHeader-end" />
|
|
84
|
+
</PageBlock>
|
|
85
|
+
</header>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<header className={clsx("ObPageHeader-root", "ObPageHeader-appbar", className)} {...props}>
|
|
91
|
+
<PageBlock className="ObPageHeader-bar" width={width} gutters={gutters}>
|
|
92
|
+
{menu && (
|
|
93
|
+
<button
|
|
94
|
+
type="button"
|
|
95
|
+
className="ObPageHeader-toggle"
|
|
96
|
+
onClick={toggle}
|
|
97
|
+
aria-label={getLocalizedString("Toggle menu")}
|
|
98
|
+
aria-expanded={open}
|
|
99
|
+
>
|
|
100
|
+
☰
|
|
101
|
+
</button>
|
|
102
|
+
)}
|
|
103
|
+
{title && <h1 className="ObPageHeader-title">{title}</h1>}
|
|
104
|
+
{actions && <div className="ObPageHeader-actions">{actions}</div>}
|
|
105
|
+
<div className="ObPageHeader-end" />
|
|
106
|
+
</PageBlock>
|
|
107
|
+
{children}
|
|
108
|
+
{menu && (
|
|
109
|
+
<AppMenuDrawer AppMenuProps={AppMenuProps} isMobile={isMobile} onClose={close} open={open}>
|
|
110
|
+
{menu}
|
|
111
|
+
</AppMenuDrawer>
|
|
112
|
+
)}
|
|
113
|
+
</header>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "./PageTitle.css";
|
|
2
|
+
|
|
3
|
+
import { Heading, type HeadingProps } from "@digdir/designsystemet-react";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
|
|
6
|
+
export type PageTitleProps = Omit<HeadingProps, "level"> & {
|
|
7
|
+
/** Heading level; the page's title is an `h1` unless the page already has one. */
|
|
8
|
+
level?: HeadingProps["level"];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The title at the top of a page's content: a Designsystemet `Heading`, `h1`, medium size.
|
|
13
|
+
*
|
|
14
|
+
* Equivalent of `PageTitle` in `@olenbetong/appframe-mui`, which portalled the title into
|
|
15
|
+
* the app bar on small screens. On the 2026 templates the site draws the toolbar and the app
|
|
16
|
+
* title lives there as breadcrumbs, so the page title is simply the first heading of the
|
|
17
|
+
* content.
|
|
18
|
+
*/
|
|
19
|
+
export function PageTitle({ className, level = 1, "data-size": size = "md", ...props }: PageTitleProps) {
|
|
20
|
+
return <Heading level={level} data-size={size} className={clsx("ObPageTitle-root", className)} {...props} />;
|
|
21
|
+
}
|
package/src/page/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./Page.js";
|
|
2
|
-
export * from "./PageBlock.js";
|
|
3
|
-
export * from "./PageHeader.js";
|
|
1
|
+
export * from "./Page.js";
|
|
2
|
+
export * from "./PageBlock.js";
|
|
3
|
+
export * from "./PageHeader.js";
|
|
4
|
+
export * from "./PageTitle.js";
|