@olenbetong/appframe-ds 1.3.5 → 1.3.7

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.
Files changed (178) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/package.json +5 -5
  3. package/scripts/copyAssets.mjs +27 -27
  4. package/src/AfLookup/Lookup.css +129 -129
  5. package/src/AfLookup/Lookup.tsx +186 -186
  6. package/src/AfLookup/LookupCombobox.css +78 -78
  7. package/src/AfLookup/LookupCombobox.tsx +237 -237
  8. package/src/AfLookup/LookupEdit.tsx +130 -130
  9. package/src/AfLookup/LookupGrid.tsx +124 -124
  10. package/src/AfLookup/index.ts +5 -5
  11. package/src/autocomplete/Autocomplete.css +256 -256
  12. package/src/autocomplete/Autocomplete.tsx +320 -320
  13. package/src/autocomplete/AutocompleteFrame.tsx +168 -168
  14. package/src/autocomplete/Combobox.tsx +286 -286
  15. package/src/autocomplete/index.ts +4 -4
  16. package/src/autocomplete/types.ts +204 -204
  17. package/src/autocomplete/utils.ts +183 -183
  18. package/src/binding/BoundNumericTextField.tsx +102 -102
  19. package/src/binding/BoundTextField.tsx +49 -49
  20. package/src/binding/CancelButton.tsx +30 -30
  21. package/src/binding/CancelIconButton.tsx +30 -30
  22. package/src/binding/DataEditToolbar.css +23 -23
  23. package/src/binding/DataEditToolbar.tsx +84 -84
  24. package/src/binding/DeleteButton.tsx +35 -35
  25. package/src/binding/DeleteIconButton.tsx +35 -35
  26. package/src/binding/RefreshButton.tsx +31 -31
  27. package/src/binding/RefreshIconButton.tsx +33 -33
  28. package/src/binding/RefreshRowIconButton.tsx +33 -33
  29. package/src/binding/SaveButton.tsx +37 -37
  30. package/src/binding/SaveIconButton.tsx +38 -38
  31. package/src/container/Container.tsx +49 -49
  32. package/src/container/index.ts +1 -1
  33. package/src/cutoff/CutOffPicker.css +12 -12
  34. package/src/cutoff/CutOffPicker.tsx +165 -165
  35. package/src/cutoff/context.tsx +194 -194
  36. package/src/cutoff/dsCutOffDates.ts +21 -21
  37. package/src/cutoff/index.ts +4 -4
  38. package/src/cutoff/utils.test.ts +59 -59
  39. package/src/cutoff/utils.ts +276 -276
  40. package/src/filter/ChipListInput.tsx +79 -79
  41. package/src/filter/FieldFilterPanel.css +150 -150
  42. package/src/filter/FieldFilterPanel.tsx +309 -309
  43. package/src/filter/FilterBuilder.css +152 -152
  44. package/src/filter/FilterBuilder.test.tsx +153 -153
  45. package/src/filter/FilterBuilder.tsx +435 -435
  46. package/src/filter/FilterEditor.css +231 -231
  47. package/src/filter/FilterEditor.test.tsx +285 -285
  48. package/src/filter/FilterEditor.tsx +75 -75
  49. package/src/filter/FilterGroupEditor.tsx +160 -160
  50. package/src/filter/FilterNameDialog.css +22 -22
  51. package/src/filter/FilterNameDialog.tsx +81 -81
  52. package/src/filter/FilterRow.tsx +117 -117
  53. package/src/filter/FilterShareDialog.css +28 -28
  54. package/src/filter/FilterShareDialog.tsx +201 -201
  55. package/src/filter/FilterStringField.tsx +78 -78
  56. package/src/filter/FilterValueEditor.tsx +239 -239
  57. package/src/filter/SavedFilterTree.css +107 -107
  58. package/src/filter/SavedFilterTree.test.tsx +94 -94
  59. package/src/filter/SavedFilterTree.tsx +218 -218
  60. package/src/filter/fieldFilter.test.ts +158 -158
  61. package/src/filter/fieldFilter.ts +139 -139
  62. package/src/filter/index.ts +27 -27
  63. package/src/filter/types.ts +38 -38
  64. package/src/filter/useDistinctValues.test.ts +102 -102
  65. package/src/filter/useDistinctValues.ts +230 -230
  66. package/src/global.d.ts +11 -11
  67. package/src/grid/AfGridColumnsPanel.tsx +118 -118
  68. package/src/grid/AfGridContext.tsx +51 -51
  69. package/src/grid/AfGridError.tsx +46 -46
  70. package/src/grid/AfHeaderFilterCell.tsx +147 -147
  71. package/src/grid/AfHeaderFilterPanel.tsx +111 -111
  72. package/src/grid/GridEditLookup.css +12 -12
  73. package/src/grid/GridEditLookup.tsx +121 -121
  74. package/src/grid/Toolbar.tsx +233 -233
  75. package/src/grid/editing.ts +100 -100
  76. package/src/grid/filter.ts +78 -78
  77. package/src/grid/formatters.ts +48 -48
  78. package/src/grid/index.css +245 -245
  79. package/src/grid/index.tsx +503 -503
  80. package/src/grid/license.ts +48 -48
  81. package/src/grid/localization.ts +369 -369
  82. package/src/grid/slots/index.tsx +334 -334
  83. package/src/grid/slots/slots.css +64 -64
  84. package/src/grid/slots/slots.test.tsx +39 -39
  85. package/src/grid/theme.tsx +138 -138
  86. package/src/grid/useAfColumns.tsx +371 -371
  87. package/src/grid/useAfCurrentIndex.ts +63 -63
  88. package/src/grid/useAfData.ts +20 -20
  89. package/src/grid/useAfFilter.ts +160 -160
  90. package/src/grid/useAfFilterFields.ts +55 -55
  91. package/src/grid/useAfGridApi.ts +71 -71
  92. package/src/grid/useAfKeyBindings.ts +36 -36
  93. package/src/grid/useAfNewItemRow.ts +258 -258
  94. package/src/grid/useAfPagination.ts +53 -53
  95. package/src/grid/useAfPersistedState.ts +230 -230
  96. package/src/grid/useAfRowEditModel.ts +145 -145
  97. package/src/grid/useAfRowGrouping.ts +47 -47
  98. package/src/grid/useAfServerAggregation.test.ts +68 -68
  99. package/src/grid/useAfServerAggregation.ts +158 -158
  100. package/src/grid/useAfSortModel.ts +84 -84
  101. package/src/i18n.ts +13 -13
  102. package/src/index.ts +14 -14
  103. package/src/input/InputAdornments.css +84 -84
  104. package/src/input/InputAdornments.tsx +102 -102
  105. package/src/input/index.ts +1 -1
  106. package/src/layout/AppMenu.tsx +74 -74
  107. package/src/layout/AppMenuDrawer.css +70 -70
  108. package/src/layout/AppMenuDrawer.tsx +122 -122
  109. package/src/layout/ErrorBoundary.tsx +162 -162
  110. package/src/layout/PageContainer.css +48 -48
  111. package/src/layout/PageContainer.tsx +41 -41
  112. package/src/layout/ResponsiveDialog.css +86 -86
  113. package/src/layout/ResponsiveDialog.tsx +55 -55
  114. package/src/layout/index.tsx +69 -69
  115. package/src/link/Link.tsx +23 -23
  116. package/src/link/index.ts +1 -1
  117. package/src/mdi/Mdi.css +138 -138
  118. package/src/mdi/Mdi.test.tsx +91 -91
  119. package/src/mdi/Mdi.tsx +141 -141
  120. package/src/mdi/MdiConfirmCloseDialog.tsx +47 -47
  121. package/src/mdi/MdiContext.tsx +59 -59
  122. package/src/mdi/MdiDocumentContext.tsx +60 -60
  123. package/src/mdi/MdiPanel.tsx +61 -61
  124. package/src/mdi/MdiRestore.test.tsx +86 -86
  125. package/src/mdi/MdiTab.tsx +30 -30
  126. package/src/mdi/controller.test.ts +382 -382
  127. package/src/mdi/controller.ts +656 -656
  128. package/src/mdi/dockviewHost.ts +132 -132
  129. package/src/mdi/fakeHost.ts +200 -200
  130. package/src/mdi/host.ts +44 -44
  131. package/src/mdi/ids.test.ts +20 -20
  132. package/src/mdi/ids.ts +18 -18
  133. package/src/mdi/index.ts +31 -31
  134. package/src/mdi/layoutRestore.test.ts +156 -156
  135. package/src/mdi/layoutRestore.ts +311 -311
  136. package/src/mdi/layoutSpec.test.ts +143 -143
  137. package/src/mdi/layoutSpec.ts +214 -214
  138. package/src/mdi/layoutStore.test.ts +93 -93
  139. package/src/mdi/layoutStore.ts +99 -99
  140. package/src/mdi/memorySettingsStore.ts +21 -21
  141. package/src/mdi/registry.ts +34 -34
  142. package/src/mdi/testTypes.ts +37 -37
  143. package/src/mdi/theme.ts +22 -22
  144. package/src/mdi/types.ts +214 -214
  145. package/src/page/Page.css +53 -53
  146. package/src/page/PageBlock.css +64 -64
  147. package/src/page/PageBlock.tsx +92 -92
  148. package/src/page/PageHeader.css +88 -88
  149. package/src/page/PageHeader.tsx +115 -115
  150. package/src/page/PageTitle.css +5 -5
  151. package/src/page/PageTitle.tsx +21 -21
  152. package/src/page/index.ts +4 -4
  153. package/src/paper/Paper.tsx +52 -52
  154. package/src/progress/LinearProgress.css +93 -93
  155. package/src/progress/LinearProgress.tsx +104 -104
  156. package/src/progress/index.ts +1 -1
  157. package/src/report-downloader/ReportDownloader.css +67 -67
  158. package/src/report-downloader/components/StatusItem.tsx +87 -87
  159. package/src/report-downloader/components/StatusList.tsx +28 -28
  160. package/src/report-downloader/index.ts +41 -41
  161. package/src/report-downloader/status.tsx +92 -92
  162. package/src/sortable/DropIndicator.css +51 -51
  163. package/src/sortable/DropIndicator.tsx +27 -27
  164. package/src/sortable/SortableItemList.css +21 -21
  165. package/src/sortable/SortableItemList.tsx +264 -264
  166. package/src/sortable/index.ts +8 -8
  167. package/src/sortable/reorderSortOrder.ts +126 -126
  168. package/src/sortable/sortOrder.ts +101 -101
  169. package/src/sortable/types.ts +9 -9
  170. package/src/sortable/useSortableContainer.ts +53 -53
  171. package/src/sortable/useSortableItem.ts +95 -95
  172. package/src/sortable/useSortableList.ts +117 -117
  173. package/src/test/happy-dom-document-class.ts +24 -24
  174. package/src/test/setup.ts +12 -12
  175. package/src/theme/useDsColorScheme.ts +53 -53
  176. package/tsconfig.build.json +9 -9
  177. package/tsconfig.json +8 -8
  178. package/vitest.config.ts +10 -10
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-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,91 +1,91 @@
1
- import { act, render, screen } from "@testing-library/react";
2
- import { useEffect } from "react";
3
- import { describe, expect, it, vi } from "vitest";
4
-
5
- import { Mdi } from "./Mdi.js";
6
- import { MdiProvider, useMdi, useMdiActiveDocument } from "./MdiContext.js";
7
- import { useMdiDocument } from "./MdiDocumentContext.js";
8
- import type { MdiApi, MdiDocumentProps, MdiDocumentTypes, MdiLayoutSpec } from "./types.js";
9
-
10
- vi.mock("@olenbetong/appframe-core", () => ({
11
- getLocalizedString: (value: string) => value,
12
- createLocalizer: () => ({
13
- getLocalizedString: (value: string) => value,
14
- localize: (parts: TemplateStringsArray) => parts.join(""),
15
- }),
16
- }));
17
-
18
- function Note({ params }: MdiDocumentProps<{ label: string }>) {
19
- let document = useMdiDocument();
20
-
21
- return (
22
- <div data-testid={document.id}>
23
- <span>{params.label}</span>
24
- <button type="button" onClick={() => document.setTitle(`${params.label}!`)}>
25
- rename
26
- </button>
27
- </div>
28
- );
29
- }
30
-
31
- function ActiveLabel() {
32
- let active = useMdiActiveDocument();
33
- return <output data-testid="active">{active?.id ?? "none"}</output>;
34
- }
35
-
36
- let apiRef: { current: MdiApi | null } = { current: null };
37
-
38
- function Grab() {
39
- let api = useMdi();
40
- useEffect(() => {
41
- apiRef.current = api;
42
- });
43
- return null;
44
- }
45
-
46
- const types: MdiDocumentTypes = {
47
- note: { component: Note, title: (params) => `Note ${params.label as string}` },
48
- tree: { component: Note, singleton: true, closable: false, title: "Tree" },
49
- };
50
-
51
- const spec: MdiLayoutSpec = {
52
- root: {
53
- direction: "horizontal",
54
- children: [
55
- { tabs: [{ type: "tree", params: { label: "Tree" } }], hideHeader: true },
56
- { tabs: [{ type: "note", key: "1", params: { label: "First" } }] },
57
- ],
58
- },
59
- };
60
-
61
- describe("Mdi", () => {
62
- it("renders the default layout through dockview and exposes the api", async () => {
63
- render(
64
- <MdiProvider types={types}>
65
- <Grab />
66
- <ActiveLabel />
67
- <div style={{ width: 800, height: 600 }}>
68
- <Mdi defaultLayout={spec} />
69
- </div>
70
- </MdiProvider>,
71
- );
72
-
73
- expect(await screen.findByText("First")).toBeInTheDocument();
74
- expect(screen.getByTestId("tree")).toBeInTheDocument();
75
- expect(apiRef.current?.getDocuments().map((document) => document.id)).toEqual(["tree", "note:1"]);
76
-
77
- await act(async () => {
78
- apiRef.current!.openDocument({ type: "note", key: "2", params: { label: "Second" } });
79
- });
80
-
81
- expect(await screen.findByText("Second")).toBeInTheDocument();
82
- expect(screen.getByTestId("active")).toHaveTextContent("note:2");
83
-
84
- await act(async () => {
85
- await apiRef.current!.close("note:2");
86
- });
87
-
88
- expect(screen.queryByText("Second")).not.toBeInTheDocument();
89
- expect(apiRef.current?.getDocument("tree")?.closable).toBe(false);
90
- });
91
- });
1
+ import { act, render, screen } from "@testing-library/react";
2
+ import { useEffect } from "react";
3
+ import { describe, expect, it, vi } from "vitest";
4
+
5
+ import { Mdi } from "./Mdi.js";
6
+ import { MdiProvider, useMdi, useMdiActiveDocument } from "./MdiContext.js";
7
+ import { useMdiDocument } from "./MdiDocumentContext.js";
8
+ import type { MdiApi, MdiDocumentProps, MdiDocumentTypes, MdiLayoutSpec } from "./types.js";
9
+
10
+ vi.mock("@olenbetong/appframe-core", () => ({
11
+ getLocalizedString: (value: string) => value,
12
+ createLocalizer: () => ({
13
+ getLocalizedString: (value: string) => value,
14
+ localize: (parts: TemplateStringsArray) => parts.join(""),
15
+ }),
16
+ }));
17
+
18
+ function Note({ params }: MdiDocumentProps<{ label: string }>) {
19
+ let document = useMdiDocument();
20
+
21
+ return (
22
+ <div data-testid={document.id}>
23
+ <span>{params.label}</span>
24
+ <button type="button" onClick={() => document.setTitle(`${params.label}!`)}>
25
+ rename
26
+ </button>
27
+ </div>
28
+ );
29
+ }
30
+
31
+ function ActiveLabel() {
32
+ let active = useMdiActiveDocument();
33
+ return <output data-testid="active">{active?.id ?? "none"}</output>;
34
+ }
35
+
36
+ let apiRef: { current: MdiApi | null } = { current: null };
37
+
38
+ function Grab() {
39
+ let api = useMdi();
40
+ useEffect(() => {
41
+ apiRef.current = api;
42
+ });
43
+ return null;
44
+ }
45
+
46
+ const types: MdiDocumentTypes = {
47
+ note: { component: Note, title: (params) => `Note ${params.label as string}` },
48
+ tree: { component: Note, singleton: true, closable: false, title: "Tree" },
49
+ };
50
+
51
+ const spec: MdiLayoutSpec = {
52
+ root: {
53
+ direction: "horizontal",
54
+ children: [
55
+ { tabs: [{ type: "tree", params: { label: "Tree" } }], hideHeader: true },
56
+ { tabs: [{ type: "note", key: "1", params: { label: "First" } }] },
57
+ ],
58
+ },
59
+ };
60
+
61
+ describe("Mdi", () => {
62
+ it("renders the default layout through dockview and exposes the api", async () => {
63
+ render(
64
+ <MdiProvider types={types}>
65
+ <Grab />
66
+ <ActiveLabel />
67
+ <div style={{ width: 800, height: 600 }}>
68
+ <Mdi defaultLayout={spec} />
69
+ </div>
70
+ </MdiProvider>,
71
+ );
72
+
73
+ expect(await screen.findByText("First")).toBeInTheDocument();
74
+ expect(screen.getByTestId("tree")).toBeInTheDocument();
75
+ expect(apiRef.current?.getDocuments().map((document) => document.id)).toEqual(["tree", "note:1"]);
76
+
77
+ await act(async () => {
78
+ apiRef.current!.openDocument({ type: "note", key: "2", params: { label: "Second" } });
79
+ });
80
+
81
+ expect(await screen.findByText("Second")).toBeInTheDocument();
82
+ expect(screen.getByTestId("active")).toHaveTextContent("note:2");
83
+
84
+ await act(async () => {
85
+ await apiRef.current!.close("note:2");
86
+ });
87
+
88
+ expect(screen.queryByText("Second")).not.toBeInTheDocument();
89
+ expect(apiRef.current?.getDocument("tree")?.closable).toBe(false);
90
+ });
91
+ });