@lotics/ui 27.6.0 → 27.7.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/docs/catalog.md CHANGED
@@ -877,7 +877,13 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
877
877
  - **`reference_field`** — `ReferenceField`: a reference to ANOTHER RECORD, rendered as a
878
878
  FIELD VALUE — the kit's inline-editor surface (so a pointer sits in the value column
879
879
  like the editors above and below it), whose press opens a PEEK of that record's facts.
880
- `name` + optional `code` + `facts`, plus the verb callbacks below. The verbs live INSIDE the
880
+ `name` + optional `code` + `facts`, plus the verb callbacks below. The peek takes THE FIELD'S
881
+ WIDTH (`inheritTriggerWidth`, as `InlineSelect` does), floored at `MIN_CONTROL_WIDTH` — a
882
+ panel narrower than the control that opened it reads as belonging to something else. So the
883
+ field truncates its name to one line and the peek's header WRAPS the whole of it: the column
884
+ stays scannable, the full value is one press away. Between the floor and `labelWidth +
885
+ MIN_CONTROL_WIDTH + 24` a `DetailTable` stacks, which is the right grammar at that width.
886
+ The verbs live INSIDE the
881
887
  peek, never on the field, and they are ALL `Button`s at one altitude — a peek is
882
888
  dialog-scale and a dialog's verbs are buttons, so mixing weights only made the reader rank
883
889
  four acts that are four acts. The row splits by WHAT EACH TOUCHES, and the spacer is that
@@ -136,7 +136,11 @@ interface Customer {
136
136
  // inline Tax ID fix-up in the Customer section.
137
137
  const KNOWN_CUSTOMERS: Customer[] = [
138
138
  { id: "cus_01", name: "Northwind Traders", code: "KH-0148", taxId: "0312456780", contact: "Mara Lindqvist", city: "Gothenburg", address: "Ringvägen 118, 4 tr, 116 61 Stockholm, Sweden", since: "2019-03-14" },
139
- { id: "cus_02", name: "Harbor Freight Lines", code: "KH-0203", taxId: "0312998820", contact: "Diego Alvarez", city: "Rotterdam", address: "Waalhaven Oostzijde 81, 3087 BM Rotterdam, Netherlands", since: "2021-11-02" },
139
+ // DELIBERATELY too long for one line. A register of tidy two-word names cannot
140
+ // show what a reference does when it does not fit — which is truncate in the
141
+ // field and wrap in the peek — so the one fixture the template opens with is the
142
+ // realistic worst case. Real customer names look like this.
143
+ { id: "cus_02", name: "Harbor Freight Lines & Coastal Forwarding Group", code: "KH-0203", taxId: "0312998820", contact: "Diego Alvarez", city: "Rotterdam", address: "Waalhaven Oostzijde 81, 3087 BM Rotterdam, Netherlands", since: "2021-11-02" },
140
144
  { id: "cus_03", name: "Summit Packaging Co.", code: "KH-0231", taxId: "0301557742", contact: "Priya Nair", city: "Singapore", address: "9 Tuas Bay Walk, #03-14, Singapore 637803", since: "2023-06-19" },
141
145
  { id: "cus_04", name: "Atlas Distribution", code: "KH-0117", taxId: "", contact: "Tom Becker", city: "Hamburg", address: "Grosser Grasbrook 9, 20457 Hamburg, Germany", since: "2018-01-30" },
142
146
  { id: "cus_05", name: "Bluewater Logistics", code: "KH-0294", taxId: "0312004455", contact: "Lena Fischer", city: "Antwerp", address: "Noorderlaan 127, 2030 Antwerpen, Belgium", since: "2022-09-08" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "27.6.0",
3
+ "version": "27.7.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./vite": {
@@ -220,6 +220,7 @@ export function ReferenceField(props: ReferenceFieldProps) {
220
220
  triggerRef={anchor}
221
221
  side="bottom"
222
222
  align="start"
223
+ inheritTriggerWidth
223
224
  >
224
225
  {/* THE KIT'S FIELD, not a lookalike. This was hand-rolled — a Pressable
225
226
  wearing copies of the field's border, radius, height and hover — and it
@@ -261,12 +262,24 @@ export function ReferenceField(props: ReferenceFieldProps) {
261
262
  rather than a hand-picked font weight; the facts are `DetailRow`s, which
262
263
  is what label-beside-value IS everywhere else on this page; and the
263
264
  verbs sit in the popover's own pinned footer rather than floating after
264
- the last fact. Width matches `Peek`'s own content width so every peek in
265
- an app is the same object.
266
- `labelWidth` is the one override, and it is not arbitrary: a `DetailTable`
267
- STACKS its columns below `labelWidth + MIN_CONTROL_WIDTH + 24`, so the
268
- page's 150 would flip a 320 popover into stacked form grammar. 88 keeps
269
- the summary side-by-side, which is the whole point of a glance. */}
265
+ the last fact.
266
+
267
+ WIDTH COMES FROM THE FIELD (`inheritTriggerWidth`), not a constant. A
268
+ fixed 320 was "every peek in an app is the same object", and the object
269
+ it was actually the same as was nothing on screen: measured on a record
270
+ page, a 558px field opened a 320px panel left-aligned under it, stopping
271
+ 238px short of the edge the reader's eye had just travelled to. A
272
+ popover narrower than the control that opened it reads as belonging to
273
+ something else. `InlineSelect` — the same shape, an inline field opening
274
+ a `triggerRef` popover — already inherits its field's width, so the two
275
+ were following different rules for one job.
276
+
277
+ The prop is floored at `MIN_CONTROL_WIDTH`, so a reference in a dense
278
+ grid column still opens something readable rather than a 90px sliver.
279
+ Between that floor and `labelWidth + MIN_CONTROL_WIDTH + 24` a
280
+ `DetailTable` STACKS its columns, which is the right answer at that
281
+ width, not a failure — 88 keeps the side-by-side grammar wherever there
282
+ is room for it, which is the whole point of a glance. */}
270
283
  {/* `PopoverContent` PARTITIONS its children: a `PopoverHeader` sits above
271
284
  the scroller, a `PopoverFooter` is pinned below it, and everything else
272
285
  scrolls between them. This component used none of that — it disabled
@@ -274,11 +287,12 @@ export function ReferenceField(props: ReferenceFieldProps) {
274
287
  is invisible at three facts and fatal at eleven: the panel ran past the
275
288
  viewport with no way to scroll, carrying its own Save button off-screen
276
289
  with it. The three-fact fixture is what hid it. */}
277
- {/* `width` on the PANEL, not `style` `style` reaches only the body, so a
278
- long referenced name in the header stretched the panel past it and the
279
- facts sat in a box wider than themselves. `maxHeight` stays on the
280
- body: that is the band that scrolls. */}
281
- <PopoverContent width={320} style={{ maxHeight: 420 }}>
290
+ {/* No `width` here at all now: a fixed panel width is applied LAST in the
291
+ style chain, so it beats `inheritTriggerWidth` passing both would have
292
+ silently kept the 320. `maxHeight` stays on the body, which is the band
293
+ that scrolls; the header keeps its own height so a wrapped two-line name
294
+ is never what scrolls out of view. */}
295
+ <PopoverContent style={{ maxHeight: 420 }}>
282
296
  <PopoverHeader>
283
297
  <DialogSectionHeadingTitle description={code}>{name}</DialogSectionHeadingTitle>
284
298
  </PopoverHeader>
@@ -256,7 +256,14 @@ const styles = StyleSheet.create({
256
256
  // padding stay (they hold the field's size); the horizontal padding goes,
257
257
  // because the host already spent CONTROL_TEXT_INSET and two insets stacked
258
258
  // shift the text 8px right the moment the field focuses.
259
- seamless: { borderColor: "transparent", backgroundColor: "transparent", paddingHorizontal: 0 },
259
+ //
260
+ // `borderWidth: 0`, not merely a transparent colour. A transparent border still
261
+ // OCCUPIES its 1px in the box model, so hiding the colour left the second inset
262
+ // in place at 1/8th the size: measured, the text moved 561 → 562 on focus — the
263
+ // same defect this style exists to fix, at the scale that survives a glance.
264
+ // Safe for height because the box is `border-box`: dropping the border changes
265
+ // the content box, never the field's 40px outer size.
266
+ seamless: { borderColor: "transparent", borderWidth: 0, backgroundColor: "transparent", paddingHorizontal: 0 },
260
267
  disabled: {
261
268
  color: colors.zinc["400"],
262
269
  outlineStyle: "none" as unknown as "solid",