@autobusal/common 1.30.0 → 1.32.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 CHANGED
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## 1.32.0
5
+
6
+ ### Added
7
+
8
+ - **Drag & drop on `File`**, the shared upload control used everywhere in the app - drop a file directly onto it instead of always going through the native picker. The control's own footprint (a single 38px-tall inline button) is unchanged everywhere it is already used; only a border/background highlight appears while dragging. A dropped file is handed to the same hidden `<input>` react-hook-form already registered, via a real dispatched `change` event, so every existing caller's validation/onChange keeps working with no changes on their end.
9
+
10
+ ### Fixed
11
+
12
+ - **A checkbox row with a long notice no longer stretches sideways.** `.row-checkbox`'s label+input are laid out `flex-direction: row-reverse`, and the row's own notice/error text (a plain div) was sharing that same row - a short notice fit fine, but a longer one (two sentences, easily) stretched the row's WIDTH to fit on one line, visibly pushing the checkbox by however long the text happened to be. Every div child of a checkbox row now gets `flex-basis: 100%`, dropping straight onto its own full-width line; the label and input are unaffected.
13
+
14
+ ## 1.31.0
15
+
16
+ ### Added
17
+
18
+ - **A `row-component` field spans the full row width**, same as `row-textarea-html` already did - what lets a Viewer form's own section headings (`SectionHeading`, admin-label's Content/styles.ts) sit as a full-width divider instead of sharing a row with whatever field lands beside them.
19
+
4
20
  ## 1.30.0
5
21
 
6
22
  ### Changed
package/File/File.tsx CHANGED
@@ -19,6 +19,7 @@ interface Props {
19
19
  const File = ({ name, value, validation, multiple, t, refs }: Props): JSX.Element => {
20
20
  const [ uploaded, setUploaded ] = useState<boolean>(false);
21
21
  const [ preview, setPreview ] = useState<boolean>(false);
22
+ const [ dragging, setDragging ] = useState<boolean>(false);
22
23
 
23
24
  const inputRef = useRef<HTMLInputElement | null>(null);
24
25
 
@@ -46,11 +47,53 @@ const File = ({ name, value, validation, multiple, t, refs }: Props): JSX.Elemen
46
47
  }
47
48
  };
48
49
 
50
+ /**
51
+ * Ferjolt Ozuni - Date: 2026-08-08
52
+ *
53
+ * A dropped file has to land on the actual hidden <input> - it is the
54
+ * one react-hook-form registered via refs(name, rules), and that
55
+ * registration is what onSave ultimately reads. The DataTransfer/
56
+ * dispatchEvent pair is the standard way to hand a File to a native
57
+ * file input programmatically: assigning to `.files` directly is
58
+ * read-only on the input itself, but an input accepts a `FileList`
59
+ * built via DataTransfer, and dispatching a real 'change' event (not
60
+ * calling the onChange prop directly) is what makes React's own
61
+ * synthetic-event system - and therefore RHF's registration - see it,
62
+ * exactly as if the browser's own file picker had fired it.
63
+ */
64
+ const onDrop = (event: React.DragEvent<HTMLDivElement>): void => {
65
+ event.preventDefault();
66
+ setDragging(false);
67
+
68
+ const dropped = event.dataTransfer.files;
69
+
70
+ if (!inputRef.current || dropped.length === 0) {
71
+ return;
72
+ }
73
+
74
+ const transfer = new DataTransfer();
75
+
76
+ Array.from(multiple ? dropped : [ dropped[0] ]).forEach(file => transfer.items.add(file));
77
+
78
+ inputRef.current.files = transfer.files;
79
+ inputRef.current.dispatchEvent(new Event('change', { bubbles: true }));
80
+ };
81
+
82
+ const onDragOver = (event: React.DragEvent<HTMLDivElement>): void => {
83
+ event.preventDefault();
84
+ setDragging(true);
85
+ };
86
+
49
87
  const type = multiple ? 'multiple' : 'single';
50
88
 
51
89
  return (
52
90
  <>
53
- <Container>
91
+ <Container
92
+ $dragging={ dragging }
93
+ onDragOver={ onDragOver }
94
+ onDragLeave={ () => setDragging(false) }
95
+ onDrop={ onDrop }
96
+ >
54
97
  <input
55
98
  { ...rest }
56
99
  type="file"
package/File/styles.ts CHANGED
@@ -1,11 +1,27 @@
1
- import styled from 'styled-components';
1
+ import styled, { css } from 'styled-components';
2
2
 
3
- export const Container = styled.div`
3
+ /**
4
+ * Ferjolt Ozuni - Date: 2026-08-08
5
+ * `$dragging` only changes the border/background while a file is being
6
+ * dragged over it - the box itself stays the same 38px-tall inline
7
+ * control everywhere this component is already used (tables, dense
8
+ * forms), rather than growing into a big dropzone that would only fit
9
+ * some of its callers.
10
+ */
11
+ export const Container = styled.div<{ $dragging?: boolean }>`
4
12
  display: flex;
5
13
  align-items: center;
6
14
  justify-content: space-between;
7
15
  gap: 10px;
8
16
  height: 38px;
17
+ border-radius: ${ props => props.theme.borderRadius };
18
+ transition: background 0.15s ease;
19
+
20
+ ${ props => props.$dragging && css`
21
+ background: ${ props.theme.primary.neutral };
22
+ outline: 2px dashed ${ props.theme.primary.normal };
23
+ outline-offset: 2px;
24
+ ` }
9
25
  `;
10
26
 
11
27
  export const ImgView = styled.img`
package/Viewer/styles.ts CHANGED
@@ -3,8 +3,25 @@ import styled from 'styled-components';
3
3
  export const Container = styled.div`
4
4
  & > div.row-checkbox {
5
5
  flex-direction: row-reverse;
6
+ flex-wrap: wrap;
6
7
  justify-content: left;
7
- height: 20px;
8
+ min-height: 20px;
9
+
10
+ /*
11
+ * Edited: Ferjolt Ozuni - Date: 2026-08-08
12
+ * A checkbox row's own notice/error text is a DIV (Notice, Item's
13
+ * error Display) sharing this row's flex layout with the label
14
+ * (a span) and the checkbox input - row-reverse was fine for just
15
+ * those two, but any row with a real notice attached (Construction's
16
+ * "enabled" checkbox is two full sentences) stretched the row's WIDTH
17
+ * to fit the text on one line instead of wrapping it, visibly pushing
18
+ * the checkbox sideways by however long the notice happened to be.
19
+ * Forcing every div child onto its own full-width line - the label
20
+ * and the input stay row-reversed exactly as before.
21
+ */
22
+ & > div {
23
+ flex-basis: 100%;
24
+ }
8
25
  }
9
26
 
10
27
  @media (min-width: 540px) {
@@ -36,6 +53,18 @@ export const Container = styled.div`
36
53
  & > div.row-textarea-html {
37
54
  flex-basis: 100% !important;
38
55
  }
56
+
57
+ /*
58
+ * Edited: Ferjolt Ozuni - Date: 2026-08-08
59
+ * A 'component' row gets the full width too, same reasoning as
60
+ * row-textarea-html above - it is how a form's own section headings
61
+ * (SectionHeading, see admin-label's Content/styles.ts) span the row
62
+ * instead of sharing it with whatever field happens to land beside
63
+ * them.
64
+ */
65
+ & > div.row-component {
66
+ flex-basis: 100% !important;
67
+ }
39
68
  }
40
69
 
41
70
  /*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/common",
3
- "version": "1.30.0",
3
+ "version": "1.32.0",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts"