@visns-studio/visns-components 5.18.1 → 5.19.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
@@ -94,7 +94,7 @@
94
94
  "react-dom": "^17.0.0 || ^18.0.0"
95
95
  },
96
96
  "name": "@visns-studio/visns-components",
97
- "version": "5.18.1",
97
+ "version": "5.19.0",
98
98
  "description": "Various packages to assist in the development of our Custom Applications.",
99
99
  "main": "src/index.js",
100
100
  "files": [
@@ -2800,6 +2800,27 @@ const DataGrid = forwardRef(
2800
2800
  return { ...acc, ...result };
2801
2801
  }, {});
2802
2802
 
2803
+ // Settings that an 'action' column renders inline render there
2804
+ // instead of the trailing Action column (avoids duplication).
2805
+ const actionColumnSettingIds = new Set(
2806
+ (columns || [])
2807
+ .filter(
2808
+ (c) =>
2809
+ c.type === 'action' &&
2810
+ Array.isArray(c.settings)
2811
+ )
2812
+ .flatMap((c) => c.settings)
2813
+ );
2814
+
2815
+ // Width to fit N action icons: tablet-mode icons have a larger
2816
+ // tap target/margin (~44px) than the default (~34px), plus cell
2817
+ // padding. Used by both action columns and the trailing column.
2818
+ const actionColumnWidthFor = (count) =>
2819
+ Math.max(
2820
+ 100,
2821
+ count * (isTabletMode ? 44 : 34) + 16
2822
+ );
2823
+
2803
2824
  const renderColumn = (column) => {
2804
2825
  let childValue;
2805
2826
  let columnId;
@@ -2951,6 +2972,37 @@ const DataGrid = forwardRef(
2951
2972
  }
2952
2973
 
2953
2974
  switch (column.type) {
2975
+ case 'action': {
2976
+ const actionSettings = (column.settings || [])
2977
+ .map((id) =>
2978
+ memoizedSettings.find(
2979
+ (s) => s.id === id
2980
+ )
2981
+ )
2982
+ .filter(Boolean);
2983
+ const width = actionColumnWidthFor(
2984
+ actionSettings.length
2985
+ );
2986
+ return {
2987
+ ...commonProps,
2988
+ name: Array.isArray(column.id)
2989
+ ? column.id.join('_')
2990
+ : column.id,
2991
+ header: column.label ?? '',
2992
+ sortable: false,
2993
+ defaultFlex: undefined,
2994
+ defaultWidth: width,
2995
+ minWidth: width,
2996
+ textAlign: 'center',
2997
+ render: ({ data }) => (
2998
+ <div className={styles.tdactions}>
2999
+ {actionSettings.map((setting) =>
3000
+ renderSetting(setting, data)
3001
+ )}
3002
+ </div>
3003
+ ),
3004
+ };
3005
+ }
2954
3006
  case 'address':
2955
3007
  return renderAddressColumn({
2956
3008
  column,
@@ -3283,37 +3335,42 @@ const DataGrid = forwardRef(
3283
3335
 
3284
3336
  const newColumns = columns.map(renderColumn);
3285
3337
 
3286
- // Function to check if any settings would be visible for any row
3287
- const hasVisibleSettings = () => {
3288
- if (memoizedSettings.length === 0) return false;
3289
-
3290
- // Check if any setting would be visible based on role permissions
3291
- return memoizedSettings.some((setting) => {
3292
- // Check role-based permissions
3338
+ // Count settings that could render in the trailing Action
3339
+ // column: role-permitted AND not claimed by an 'action' column.
3340
+ // Per-row conditions (active/condition/hide) may hide more at
3341
+ // runtime, but the column must fit the maximum case.
3342
+ const trailingSettings = memoizedSettings.filter(
3343
+ (setting) => {
3344
+ if (actionColumnSettingIds.has(setting.id)) {
3345
+ return false;
3346
+ }
3293
3347
  if (
3294
3348
  setting.roles &&
3295
3349
  Array.isArray(setting.roles) &&
3296
3350
  setting.roles.length > 0
3297
3351
  ) {
3298
- const hasRequiredRole = setting.roles.some(
3299
- (requiredRole) =>
3300
- userProfile?.roles?.some(
3301
- (userRole) =>
3302
- userRole.name === requiredRole
3303
- )
3352
+ return setting.roles.some((requiredRole) =>
3353
+ userProfile?.roles?.some(
3354
+ (userRole) =>
3355
+ userRole.name === requiredRole
3356
+ )
3304
3357
  );
3305
- return hasRequiredRole;
3306
3358
  }
3307
3359
  // If no roles specified, setting is visible
3308
3360
  return true;
3309
- });
3310
- };
3361
+ }
3362
+ );
3363
+
3364
+ if (trailingSettings.length > 0) {
3365
+ const actionColumnWidth = actionColumnWidthFor(
3366
+ trailingSettings.length
3367
+ );
3311
3368
 
3312
- if (hasVisibleSettings()) {
3313
3369
  newColumns.push({
3314
3370
  name: 'setting',
3315
3371
  header: 'Action',
3316
- defaultWidth: 100,
3372
+ defaultWidth: actionColumnWidth,
3373
+ minWidth: actionColumnWidth,
3317
3374
  textAlign: 'center',
3318
3375
  textVerticalAlign:
3319
3376
  style && style.text_vertical_align
@@ -3322,9 +3379,16 @@ const DataGrid = forwardRef(
3322
3379
  render: ({ data }) => {
3323
3380
  return (
3324
3381
  <div className={styles.tdactions}>
3325
- {memoizedSettings.map((setting) =>
3326
- renderSetting(setting, data)
3327
- )}
3382
+ {memoizedSettings
3383
+ .filter(
3384
+ (setting) =>
3385
+ !actionColumnSettingIds.has(
3386
+ setting.id
3387
+ )
3388
+ )
3389
+ .map((setting) =>
3390
+ renderSetting(setting, data)
3391
+ )}
3328
3392
  </div>
3329
3393
  );
3330
3394
  },
@@ -3405,7 +3469,7 @@ const DataGrid = forwardRef(
3405
3469
  .catch((error) => {
3406
3470
  console.error('Error in fetching dropdown data: ', error);
3407
3471
  });
3408
- }, [columns, filterDataSource, memoizedSettings]);
3472
+ }, [columns, filterDataSource, memoizedSettings, isTabletMode]);
3409
3473
 
3410
3474
  // Force re-render when filterDataSource updates to ensure dropdown filters get their data
3411
3475
  const [renderKey, setRenderKey] = useState(0);