@visns-studio/visns-components 6.3.1 → 6.3.3

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
@@ -91,7 +91,7 @@
91
91
  "react-dom": "^17.0.0 || ^18.0.0"
92
92
  },
93
93
  "name": "@visns-studio/visns-components",
94
- "version": "6.3.1",
94
+ "version": "6.3.3",
95
95
  "description": "Various packages to assist in the development of our Custom Applications.",
96
96
  "main": "src/index.js",
97
97
  "files": [
@@ -4630,44 +4630,37 @@ const DataGrid = forwardRef(
4630
4630
 
4631
4631
  {/* Opt-in colour legend (config key `legend`: array of
4632
4632
  {colour, label}); entries without a colour render as
4633
- plain lead-in text */}
4633
+ plain lead-in text.
4634
+
4635
+ Styling lives in DataGrid.module.scss (`.legend` and
4636
+ friends) rather than inline, so a consuming project can
4637
+ actually reach it — see the notes there. The only inline
4638
+ style left is the swatch's own fill, which is data from
4639
+ the config rather than a design decision. */}
4634
4640
  {Array.isArray(legend) && legend.length > 0 && (
4635
- <div
4636
- style={{
4637
- display: 'flex',
4638
- flexWrap: 'wrap',
4639
- alignItems: 'center',
4640
- gap: '14px',
4641
- padding: '6px 4px 8px',
4642
- fontSize: '0.8rem',
4643
- color: '#555',
4644
- }}
4645
- >
4646
- {legend.map((item, index) => (
4647
- <span
4648
- key={index}
4649
- style={{
4650
- display: 'inline-flex',
4651
- alignItems: 'center',
4652
- gap: '6px',
4653
- }}
4654
- >
4655
- {(item.colour || item.color) && (
4656
- <span
4657
- style={{
4658
- width: '14px',
4659
- height: '14px',
4660
- borderRadius: '3px',
4661
- backgroundColor:
4662
- item.colour || item.color,
4663
- display: 'inline-block',
4664
- flexShrink: 0,
4665
- }}
4666
- />
4667
- )}
4668
- {item.label}
4669
- </span>
4670
- ))}
4641
+ <div className={styles.legend}>
4642
+ {legend.map((item, index) => {
4643
+ const swatch = item.colour || item.color;
4644
+
4645
+ return (
4646
+ <span
4647
+ key={index}
4648
+ className={
4649
+ swatch
4650
+ ? styles.legendItem
4651
+ : `${styles.legendItem} ${styles.legendLead}`
4652
+ }
4653
+ >
4654
+ {swatch && (
4655
+ <span
4656
+ className={styles.legendSwatch}
4657
+ style={{ backgroundColor: swatch }}
4658
+ />
4659
+ )}
4660
+ {item.label}
4661
+ </span>
4662
+ );
4663
+ })}
4671
4664
  </div>
4672
4665
  )}
4673
4666
 
@@ -205,8 +205,16 @@
205
205
  }
206
206
  }
207
207
 
208
+ /* The gallery modal's close control — this class is consumed by
209
+ modals/GalleryModal.jsx, which imports this stylesheet (DataGrid.jsx itself
210
+ never uses it). Same hardening as the header close in Form.module.scss; the
211
+ long note on the svg block there explains why a close glyph needs an
212
+ explicit box and `flex: none` rather than trusting its size attributes. */
208
213
  .modal__close {
209
214
  width: max-content;
215
+ min-width: 2rem;
216
+ min-height: 2rem;
217
+ box-sizing: border-box;
210
218
  background: rgba(var(--paragraph-rgb), 0.05);
211
219
  cursor: pointer;
212
220
  padding: 0.25rem;
@@ -225,6 +233,9 @@
225
233
  }
226
234
 
227
235
  svg {
236
+ width: 1.25rem;
237
+ height: 1.25rem;
238
+ flex: none;
228
239
  color: var(--primary-color);
229
240
  display: block;
230
241
  }
@@ -526,6 +537,94 @@
526
537
  justify-content: flex-end;
527
538
  }
528
539
 
540
+ /* ============================================================================
541
+ Colour legend
542
+ ----------------------------------------------------------------------------
543
+ The opt-in caption above the grid (config key `legend`: an array of
544
+ `{ colour | color, label }`, where an entry carrying no colour renders as
545
+ lead-in text introducing the swatches after it).
546
+
547
+ This was inline styles on the elements themselves — `fontSize: '0.8rem'`,
548
+ `color: '#555'`, a hardcoded 14px swatch, `padding: '6px 4px 8px'`. Inline
549
+ styles are unreachable from a consuming project's stylesheet, so the one
550
+ thing a legend needs to be — tuned to the app it sits in — was the one
551
+ thing it could not be. It was also set off any scale in the library: 0.8rem
552
+ falls between two steps of the type ramp, and #555 is a grey that appears
553
+ nowhere else.
554
+
555
+ It is a caption for the table below it, so it is set as one: the same
556
+ `--font-size-xs`, `--muted-color` and `--font-weight-semibold` the grid's
557
+ own header row uses, so the two label rows stacked above the data read as
558
+ one family. It deliberately stops short of that header's uppercase and
559
+ 0.06em tracking — legend labels are sentences ("No Goods Received entered
560
+ yet"), not column names, and setting a sentence in caps would undo the
561
+ quiet the rest of this is after.
562
+
563
+ Density hooks, following the `--nav-*` set documented at the top of
564
+ Navigation.module.scss: every declaration below is written
565
+ `var(--hook, <the value it always had>)`, so an unset hook is a no-op and a
566
+ project retunes from `:root` with no fork, no prop and no class of its own.
567
+ The plant-floor tablet case is the one that needs them — 12px is small when
568
+ the screen is at arm's length on a bench.
569
+
570
+ --grid-legend-font-size label type size.
571
+ default: var(--font-size-xs, 0.75rem)
572
+ --grid-legend-gap space between entries along a line.
573
+ default: var(--spacing-md, 1rem)
574
+ --grid-legend-swatch-size the colour chip. default: 0.875rem (14px)
575
+ ========================================================================= */
576
+
577
+ .legend {
578
+ display: flex;
579
+ flex-wrap: wrap;
580
+ align-items: center;
581
+ /* Row gap and column gap differ on purpose: a legend that wraps (despatch
582
+ runs to seven entries) needs its lines closer together than its entries
583
+ are along a line, or the wrapped rows read as separate captions. */
584
+ gap: var(--spacing-sm, 0.5rem)
585
+ var(--grid-legend-gap, var(--spacing-md, 1rem));
586
+ /* A caption belongs to the thing it describes, so it sits nearer the grid
587
+ than the toolbar row above it — which is also what stops it crowding
588
+ that row, the complaint this change came from. No horizontal padding:
589
+ `.dataGridContainer` has none either, so the caption starts on the
590
+ grid's own left edge rather than floating 4px off it. */
591
+ margin: var(--spacing-md, 1rem) 0 var(--spacing-sm, 0.5rem);
592
+ padding: 0;
593
+ font-size: var(--grid-legend-font-size, var(--font-size-xs, 0.75rem));
594
+ line-height: 1.4;
595
+ color: var(--muted-color, #6b7688);
596
+ }
597
+
598
+ .legendItem {
599
+ display: inline-flex;
600
+ align-items: center;
601
+ gap: var(--spacing-xs, 0.25rem);
602
+ }
603
+
604
+ /* The lead-in entry: a legend line with no colour of its own, labelling the
605
+ swatches that follow. Weight and a darker ink rather than a different size,
606
+ so it introduces the row without breaking its line. */
607
+ .legendLead {
608
+ font-weight: var(--font-weight-semibold, 600);
609
+ color: var(--paragraph-color, #374151);
610
+ }
611
+
612
+ .legendSwatch {
613
+ width: var(--grid-legend-swatch-size, 0.875rem);
614
+ height: var(--grid-legend-swatch-size, 0.875rem);
615
+ flex-shrink: 0;
616
+ display: inline-block;
617
+ border-radius: var(--radius-sm, 6px);
618
+ /* These are row tints, so they are pale by design — #FFEAEA has no edge
619
+ of its own against a white page and the swatch dissolves into it. A
620
+ low-alpha ink hairline gives every chip its shape back while staying
621
+ invisible against the darker ones. `--border-color` is the wrong token
622
+ here: it is tuned to be barely there on a white surface, which is
623
+ exactly where it is needed most. */
624
+ border: 1px solid rgba(var(--paragraph-color-rgb, 34, 30, 51), 0.18);
625
+ box-sizing: border-box;
626
+ }
627
+
529
628
  /* Date field styling for uniform width */
530
629
  :global {
531
630
  // Target date cells specifically
@@ -708,24 +708,52 @@ input[type='file']:hover {
708
708
  font-size: 1.15em;
709
709
  }
710
710
 
711
+ /* The "Edit Canvas" modal's close control (Field.jsx). Hardened
712
+ the same way as the header close in Form.module.scss — see the
713
+ note on the svg block there. */
711
714
  .modal__close {
712
715
  width: max-content;
716
+ min-width: 2rem;
717
+ min-height: 2rem;
713
718
  position: absolute;
714
719
  right: 5px;
715
720
  top: 5px;
716
721
  box-sizing: border-box;
717
- background: rgba(var(--primary-color), 1.08);
722
+ /* Was `rgba(var(--primary-color), 1.08)`, which is not a
723
+ colour: `--primary-color` is a hex, rgba() wants three
724
+ channels, and an alpha above 1 is out of range either way.
725
+ The declaration was invalid and dropped, so this button had
726
+ no background at all. It sits on `&__header`, which is
727
+ `var(--primary-color)`, so what it wants is a light lift off
728
+ that ground — the same treatment the equivalent control in
729
+ GenericFormBuilder.module.scss uses on its coloured header. */
730
+ background: rgba(255, 255, 255, 0.15);
718
731
  cursor: pointer;
719
732
  padding: 8px 8px;
720
733
  margin: 0;
721
734
  outline: none;
722
735
  border: none;
723
736
  border-radius: var(--br);
724
- display: block;
737
+ display: flex;
738
+ align-items: center;
739
+ justify-content: center;
725
740
  line-height: 1;
741
+ transition: background 0.2s ease;
742
+
743
+ &:hover {
744
+ background: rgba(255, 255, 255, 0.25);
745
+ }
726
746
 
727
747
  svg {
728
- color: var(--secondary-color);
748
+ width: 1.25rem;
749
+ height: 1.25rem;
750
+ flex: none;
751
+ /* The header behind this is `--primary-color`, so the
752
+ glyph is set against it rather than in a brand hue that
753
+ may be a near-match for it. Field.jsx also passes
754
+ `color="#FFF"`, which lucide writes as a `stroke`
755
+ attribute; this keeps the two in agreement. */
756
+ color: #fff;
729
757
  display: block;
730
758
  }
731
759
  }
@@ -242,23 +242,63 @@ input[type='file'] {
242
242
  justify-content: center;
243
243
  width: 2rem;
244
244
  height: 2rem;
245
+ /* The box is stated three ways on purpose. `width`/`height` alone is not a
246
+ box a consuming app cannot move: every one of these buttons lives under
247
+ whatever ambient `button { … }` rule the host stylesheet carries, and
248
+ with the library's own `* { box-sizing: border-box }` in play, a host
249
+ padding rule eats this button's *content* box rather than growing it.
250
+ The min-* pair holds the outer size and `box-sizing` states the
251
+ assumption rather than inheriting it — but see the svg block for what
252
+ actually keeps the glyph safe. */
253
+ min-width: 2rem;
254
+ min-height: 2rem;
255
+ box-sizing: border-box;
245
256
  flex: none;
246
257
  background: none;
247
258
  cursor: pointer;
248
259
  padding: 0;
249
260
  margin: 0;
250
261
  border: none;
251
- border-radius: var(--radius-sm);
262
+ border-radius: var(--radius-sm, 6px);
252
263
  line-height: 1;
253
- transition: background-color var(--speed) var(--ease);
264
+ transition: background-color var(--speed, 0.18s) var(--ease, ease);
254
265
 
255
266
  &:hover {
256
- background: var(--hover-color);
267
+ background: var(--hover-color, rgba(var(--paragraph-color-rgb, 34, 30, 51), 0.06));
257
268
  }
258
269
 
259
270
  svg {
260
- color: var(--muted-color);
271
+ /* This is the rule that stops the icon disappearing.
272
+
273
+ An `<svg width="24" height="24">` inside a flex container is a flex
274
+ item with the default `flex-shrink: 1`, so when the button's content
275
+ box is squeezed the glyph shrinks with it — all the way down.
276
+ Hartway's plant-floor stylesheet carries
277
+ `body.tablet-mode button:not([class*='InovuaReactDataGrid'])
278
+ { padding: 8px 14px }`,
279
+ which outweighs this module's single class (0,2,2 against 0,1,0) and
280
+ left a 2rem border-box button with a 4px content box; the X
281
+ collapsed with it and read as a smudge at the end of the header.
282
+
283
+ `flex: none` refuses to shrink, and the explicit width/height also
284
+ makes the glyph immune to the `width: 100%` sizing pattern used on
285
+ svgs elsewhere in this library. Both are needed: the size fixes the
286
+ basis, `flex: none` stops it being overruled. Sized here rather than
287
+ trusting the `size` prop at each call site, so every modal header
288
+ agrees on one glyph. */
289
+ width: 1.25rem;
290
+ height: 1.25rem;
291
+ flex: none;
292
+ /* Recessive, but a control the user has to be able to find has no
293
+ business being fainter than the body text around it. */
294
+ color: var(--muted-color, #6b7688);
261
295
  display: block;
296
+ transition: color var(--speed, 0.18s) var(--ease, ease);
297
+ }
298
+
299
+ &:hover svg,
300
+ &:focus-visible svg {
301
+ color: var(--paragraph-color, #374151);
262
302
  }
263
303
  }
264
304
 
@@ -741,8 +741,13 @@ select:not(:placeholder-shown) + .fi__span {
741
741
  letter-spacing: 0.01em;
742
742
  }
743
743
 
744
+ /* The form builder's modal close control (GenericFormBuilder.jsx, two call
745
+ sites). Hardened the same way as the header close in Form.module.scss — see
746
+ the note on the svg block there. */
744
747
  .modal__close {
745
748
  width: max-content;
749
+ min-width: 2rem;
750
+ min-height: 2rem;
746
751
  position: absolute;
747
752
  right: 8px;
748
753
  top: 8px;
@@ -754,7 +759,9 @@ select:not(:placeholder-shown) + .fi__span {
754
759
  outline: none;
755
760
  border: none;
756
761
  border-radius: 6px;
757
- display: block;
762
+ display: flex;
763
+ align-items: center;
764
+ justify-content: center;
758
765
  line-height: 1;
759
766
  transition: background 0.2s ease;
760
767
 
@@ -764,7 +771,13 @@ select:not(:placeholder-shown) + .fi__span {
764
771
  }
765
772
 
766
773
  .modal__close svg {
767
- color: var(--secondary-color);
774
+ width: 1.25rem;
775
+ height: 1.25rem;
776
+ flex: none;
777
+ /* `.modal__header` above is `var(--primary-color)`, so the glyph is set
778
+ against that ground rather than in a second brand hue that may be a
779
+ near-match for it — which is what `--secondary-color` was doing here. */
780
+ color: #fff;
768
781
  display: block;
769
782
  }
770
783