@visns-studio/visns-components 6.23.1 → 6.24.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/package.json
CHANGED
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
94
94
|
},
|
|
95
95
|
"name": "@visns-studio/visns-components",
|
|
96
|
-
"version": "6.
|
|
96
|
+
"version": "6.24.0",
|
|
97
97
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
98
98
|
"main": "src/index.js",
|
|
99
99
|
"files": [
|
|
@@ -43,6 +43,7 @@ import NativeDateFilterEditor from './columns/NativeDateFilterEditor';
|
|
|
43
43
|
import SelectFilterEditor from './columns/SelectFilterEditor';
|
|
44
44
|
import { toast } from 'react-toastify';
|
|
45
45
|
import fetchUtil from '../utils/fetchUtil';
|
|
46
|
+
import { resolveFormVariant } from '../utils/formLayout';
|
|
46
47
|
import { confirmDialog } from './utils/ConfirmDialog';
|
|
47
48
|
import {
|
|
48
49
|
useDensity,
|
|
@@ -1431,7 +1432,14 @@ const DataGrid = forwardRef(
|
|
|
1431
1432
|
// A rowColours tint is an inline background on the row
|
|
1432
1433
|
// element; the class lets the stylesheet clear the zebra
|
|
1433
1434
|
// band that would otherwise paint over it on odd rows.
|
|
1434
|
-
|
|
1435
|
+
// The literal twin exists for global-datagrid.css, which
|
|
1436
|
+
// cannot see the hashed module class: the 2026-pass row
|
|
1437
|
+
// surface there is `!important` (it has to outrank the
|
|
1438
|
+
// vendored theme) and would beat the inline tint, so that
|
|
1439
|
+
// rule stands down on rows carrying this class.
|
|
1440
|
+
findRowColour(rowProps?.data)
|
|
1441
|
+
? `${styles.tintedRow} vs-datagrid--row-tinted`
|
|
1442
|
+
: '',
|
|
1435
1443
|
]
|
|
1436
1444
|
.filter(Boolean)
|
|
1437
1445
|
.join(' '),
|
|
@@ -6774,10 +6782,14 @@ const DataGrid = forwardRef(
|
|
|
6774
6782
|
/* A record form is the case a side sheet is for: the list
|
|
6775
6783
|
stays visible behind it, a long form scrolls naturally
|
|
6776
6784
|
instead of stretching the dialog, and the width is fixed
|
|
6777
|
-
so the fields keep one measure on every monitor.
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6785
|
+
so the fields keep one measure on every monitor. That is
|
|
6786
|
+
the library default, so forms land in the sheet unless
|
|
6787
|
+
something says otherwise. A whole project can flip to the
|
|
6788
|
+
centred dialog with `setDefaultFormLayout('modal')` at
|
|
6789
|
+
bootstrap, and a single view that wants the other
|
|
6790
|
+
presentation overrides it with `form.layout: "modal"` or
|
|
6791
|
+
`form.layout: "sheet"`. */
|
|
6792
|
+
variant={resolveFormVariant(formData.layout)}
|
|
6781
6793
|
size={formData.modalSize || 'medium'}
|
|
6782
6794
|
>
|
|
6783
6795
|
<Form
|
|
@@ -47,6 +47,7 @@ import { saveAs } from 'file-saver';
|
|
|
47
47
|
import { toast } from 'react-toastify';
|
|
48
48
|
import imageCompression from 'browser-image-compression';
|
|
49
49
|
import fetchUtil from '../../utils/fetchUtil';
|
|
50
|
+
import { resolveFormVariant } from '../../utils/formLayout';
|
|
50
51
|
import {
|
|
51
52
|
CheckCircle as CircleCheck,
|
|
52
53
|
Copy,
|
|
@@ -4267,7 +4268,7 @@ function GenericDetail({
|
|
|
4267
4268
|
title={formData.title || 'Edit Details'}
|
|
4268
4269
|
closeOnDocumentClick={false}
|
|
4269
4270
|
verticalAlign={formData.verticalAlign || 'center'}
|
|
4270
|
-
variant={formData.layout
|
|
4271
|
+
variant={resolveFormVariant(formData.layout)}
|
|
4271
4272
|
size={formData.modalSize || 'medium'}
|
|
4272
4273
|
>
|
|
4273
4274
|
<Form
|
|
@@ -647,10 +647,23 @@ body.tablet-mode .InovuaReactDataGrid__cell.cell-word-wrap > div {
|
|
|
647
647
|
.InovuaReactDataGrid__row {
|
|
648
648
|
min-height: 44px !important;
|
|
649
649
|
border: 0 !important;
|
|
650
|
-
background: var(--dgx-surface) !important;
|
|
651
650
|
transition: background 140ms cubic-bezier(0.4, 0, 0.2, 1) !important;
|
|
652
651
|
}
|
|
653
652
|
|
|
653
|
+
/* The surface is on its own rule so it can stand down for a `rowColours`
|
|
654
|
+
tint. That tint arrives as an INLINE background set by rowStyle in
|
|
655
|
+
DataGrid.jsx, and inline loses to any `!important` — so painting the
|
|
656
|
+
surface `!important` on every row silently killed the priority/urgency
|
|
657
|
+
colours projects configure (tasks grids and the like). Rows with a tint
|
|
658
|
+
are marked `vs-datagrid--row-tinted` (the literal twin of the module's
|
|
659
|
+
hashed `.tintedRow`); on those rows nothing is declared here and the
|
|
660
|
+
inline tint wins over the vendored theme's non-important zebra.
|
|
661
|
+
Hover and selected below stay `!important` on every row by design —
|
|
662
|
+
they have always outranked the tint. */
|
|
663
|
+
.InovuaReactDataGrid__row:not(.vs-datagrid--row-tinted) {
|
|
664
|
+
background: var(--dgx-surface) !important;
|
|
665
|
+
}
|
|
666
|
+
|
|
654
667
|
.InovuaReactDataGrid__row:hover,
|
|
655
668
|
.InovuaReactDataGrid__row--hover-target:hover {
|
|
656
669
|
background: var(--dgx-hover) !important;
|
package/src/index.js
CHANGED
|
@@ -14,6 +14,14 @@ import {
|
|
|
14
14
|
SECONDARY_GRID_HEIGHT,
|
|
15
15
|
} from './components/utils/useDensity';
|
|
16
16
|
import { readBuildEnv, buildEnv } from './components/utils/buildEnv';
|
|
17
|
+
// Project-wide default for how record CRUD forms are presented — the side
|
|
18
|
+
// sheet unless an app calls setDefaultFormLayout('modal') at bootstrap. A
|
|
19
|
+
// form config's own `layout` still wins.
|
|
20
|
+
import {
|
|
21
|
+
setDefaultFormLayout,
|
|
22
|
+
getDefaultFormLayout,
|
|
23
|
+
resolveFormVariant,
|
|
24
|
+
} from './utils/formLayout';
|
|
17
25
|
|
|
18
26
|
/** CRM Components */
|
|
19
27
|
import AsyncSelect from './components/AsyncSelect';
|
|
@@ -478,6 +486,7 @@ export {
|
|
|
478
486
|
GenericQuote,
|
|
479
487
|
GenericReport,
|
|
480
488
|
GenericSort,
|
|
489
|
+
getDefaultFormLayout,
|
|
481
490
|
GroupedReportRenderer,
|
|
482
491
|
hasChallengeState,
|
|
483
492
|
ImpersonateGate,
|
|
@@ -523,6 +532,7 @@ export {
|
|
|
523
532
|
resolveAuthEndpoints,
|
|
524
533
|
resolveClientPaths,
|
|
525
534
|
resolveClientProtocol,
|
|
535
|
+
resolveFormVariant,
|
|
526
536
|
// Passkeys (WebAuthn). Exported so a consuming app can build its own
|
|
527
537
|
// enrolment screen against the same marshalling the login screen uses.
|
|
528
538
|
base64UrlToBytes,
|
|
@@ -536,6 +546,7 @@ export {
|
|
|
536
546
|
SectionTypeSelector,
|
|
537
547
|
SelectList,
|
|
538
548
|
Select,
|
|
549
|
+
setDefaultFormLayout,
|
|
539
550
|
showConfirmDialog,
|
|
540
551
|
SortableList,
|
|
541
552
|
StagePopupModal,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-wide default for how record CRUD forms are presented.
|
|
3
|
+
*
|
|
4
|
+
* StandardModal can draw a form either as a centred dialog (`variant="modal"`)
|
|
5
|
+
* or as a right-side slide-in sheet (`variant="sheet"`). The library ships with
|
|
6
|
+
* the sheet as its default so existing projects keep the presentation they
|
|
7
|
+
* already have. A consuming app that prefers the classic centred dialog calls
|
|
8
|
+
* `setDefaultFormLayout('modal')` once at bootstrap (before the first render)
|
|
9
|
+
* and every DataGrid / GenericDetail form follows.
|
|
10
|
+
*
|
|
11
|
+
* An individual form config still wins in both directions: set
|
|
12
|
+
* `layout: 'modal'` or `layout: 'sheet'` on the form and that form ignores the
|
|
13
|
+
* project default.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** The two presentations StandardModal understands. */
|
|
17
|
+
const VALID_LAYOUTS = ['modal', 'sheet'];
|
|
18
|
+
|
|
19
|
+
/** Library default — the side sheet, unless a project opts out. */
|
|
20
|
+
let defaultFormLayout = 'sheet';
|
|
21
|
+
|
|
22
|
+
/** Warn at most once so a bad bootstrap call is not a console flood. */
|
|
23
|
+
let warnedInvalidLayout = false;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set the project-wide default presentation for record forms.
|
|
27
|
+
* @param {'modal'|'sheet'} layout - Presentation to use when a form config does
|
|
28
|
+
* not specify its own `layout`.
|
|
29
|
+
* @returns {void} Anything other than 'modal' or 'sheet' is ignored.
|
|
30
|
+
*/
|
|
31
|
+
export const setDefaultFormLayout = (layout) => {
|
|
32
|
+
if (!VALID_LAYOUTS.includes(layout)) {
|
|
33
|
+
if (!warnedInvalidLayout) {
|
|
34
|
+
warnedInvalidLayout = true;
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.warn(
|
|
37
|
+
`setDefaultFormLayout: expected 'modal' or 'sheet', received ${JSON.stringify(layout)}. Keeping '${defaultFormLayout}'.`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
defaultFormLayout = layout;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Read the current project-wide default.
|
|
48
|
+
* @returns {'modal'|'sheet'} The default presentation for record forms.
|
|
49
|
+
*/
|
|
50
|
+
export const getDefaultFormLayout = () => defaultFormLayout;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the StandardModal variant for one form.
|
|
54
|
+
* @param {string} [layout] - The form config's own `layout`, if it has one.
|
|
55
|
+
* @returns {'modal'|'sheet'} The form's own layout when it is valid, otherwise
|
|
56
|
+
* the project-wide default.
|
|
57
|
+
*/
|
|
58
|
+
export const resolveFormVariant = (layout) =>
|
|
59
|
+
(VALID_LAYOUTS.includes(layout) ? layout : defaultFormLayout);
|