@entropy-softworks/ui 2026.910.2 → 2026.911.1

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
@@ -7,6 +7,30 @@ are CalVer — `YYYY.M.D` of the publish date, with leading zeros dropped (npm's
7
7
  them), matching the `entropy-auth` crate. The `0.1.0` entry below predates the switch and was never
8
8
  published to npm.
9
9
 
10
+ ## 2026.911.1
11
+
12
+ ### Added
13
+ - `DataTable` takes `resizable`, which lets the operator drag the boundary
14
+ between two columns. Widths seed from the measured container by each column's
15
+ `flex`, so a resizable table still fills its space without pixel widths at
16
+ the call site, and a drag moves width between the pair either side of the
17
+ handle rather than growing the table — the total is unchanged, so columns to
18
+ the right do not crawl sideways. A manual drag survives a window resize.
19
+ `distributeColumnWidths` and `resizeColumnPair` are exported and pure, with
20
+ seven tests covering flex weighting, fixed columns, the minimum width, and
21
+ the total-preserving property.
22
+
23
+ ## 2026.910.3
24
+
25
+ ### Added
26
+ - `SocialConnections` takes a `custom` list of providers this package ships no
27
+ brand mark for — Okta, Keycloak, a second Access instance — rendered after
28
+ the built-ins so learned button positions do not move. Each carries the
29
+ operator's own `iconUrl`; a blank, malformed or unreachable URL falls back to
30
+ a neutral key glyph rather than an empty square, so the button is always
31
+ pressable and always labelled. `customIcon` is exported and pure so the
32
+ fallback rule is testable without a render runtime.
33
+
10
34
  ## 2026.8.42
11
35
 
12
36
  ### Fixed
@@ -29,6 +29,20 @@ export interface DataTableProps<T> {
29
29
  emptyState?: React.ReactNode;
30
30
  /** Fallback empty message when `emptyState` is not provided. */
31
31
  emptyMessage?: string;
32
+ /**
33
+ * Let the operator drag the boundary between two columns.
34
+ *
35
+ * Off by default, because it costs a measured container and per-column
36
+ * width state — a table that never needs it should not pay for it. On, the
37
+ * columns start at their `flex` share of the measured width (so the table
38
+ * still fills its space) and a drag moves width between the pair either
39
+ * side of the handle rather than growing the table.
40
+ *
41
+ * Web-oriented: the handles are 8px targets suited to a pointer. They
42
+ * render on native too and work, but a phone is not where a column gets
43
+ * dragged.
44
+ */
45
+ resizable?: boolean;
32
46
  className?: string;
33
47
  }
34
48
  /**
@@ -37,6 +51,26 @@ export interface DataTableProps<T> {
37
51
  * without a render host.
38
52
  */
39
53
  export declare function resolveColumnStyle<T>(column: DataTableColumn<T>): ViewStyle;
54
+ /** Below this a cell shows nothing but its own padding. */
55
+ export declare const MIN_COLUMN_WIDTH = 64;
56
+ /**
57
+ * Starting widths for a resizable table: the container divided by flex, with
58
+ * fixed-width columns taken out first.
59
+ *
60
+ * Pure so the layout rule is testable without a render host, and so the answer
61
+ * is the same on the first frame as after a resize — a table that measures
62
+ * itself and then computes differently is a table that jumps.
63
+ */
64
+ export declare function distributeColumnWidths<T>(columns: DataTableColumn<T>[], totalWidth: number, minWidth?: number): number[];
65
+ /**
66
+ * Apply one drag to a pair of adjacent columns.
67
+ *
68
+ * Resizing takes width from the NEIGHBOUR rather than from the table, so the
69
+ * total stays put and the columns to the right do not crawl sideways as the
70
+ * handle moves. Both sides clamp at `minWidth`, so a drag past the limit stops
71
+ * instead of inverting the pair.
72
+ */
73
+ export declare function resizeColumnPair(widths: number[], index: number, delta: number, minWidth?: number): number[];
40
74
  /** Which body the table renders: skeleton rows, an empty placeholder, or data. */
41
75
  export type DataTableBodyMode = "loading" | "empty" | "data";
42
76
  /**
@@ -55,5 +89,5 @@ export declare function dataTableBodyMode(loading: boolean, rowCount: number): D
55
89
  * `emptyMessage`). Columns size by fixed `width` or `flex`, support custom
56
90
  * `render`, and alignment.
57
91
  */
58
- export declare function DataTable<T>({ columns, data, keyExtractor, onRowPress, loading, loadingRowCount, emptyState, emptyMessage, className, }: DataTableProps<T>): React.JSX.Element;
92
+ export declare function DataTable<T>({ columns, data, keyExtractor, onRowPress, loading, loadingRowCount, emptyState, emptyMessage, resizable, className, }: DataTableProps<T>): React.JSX.Element;
59
93
  //# sourceMappingURL=data-table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAK9F,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IACrC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,iEAAiE;IACjE,YAAY,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,0DAA0D;IAC1D,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,CAY3E;AAED,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAKvF;AA0ED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAC3B,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,OAAe,EACf,eAAmB,EACnB,UAAU,EACV,YAAwB,EACxB,SAAS,GACV,EAAE,cAAc,CAAC,CAAC,CAAC,qBA0CnB"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAKtB,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IACrC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,iEAAiE;IACjE,YAAY,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,0DAA0D;IAC1D,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,CAY3E;AAED,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAYnC;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,EAC7B,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAmB,GAC1B,MAAM,EAAE,CAeV;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,QAAQ,SAAmB,GAC1B,MAAM,EAAE,CAWV;AAoBD,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAKvF;AA4JD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAC3B,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,OAAe,EACf,eAAmB,EACnB,UAAU,EACV,YAAwB,EACxB,SAAiB,EACjB,SAAS,GACV,EAAE,cAAc,CAAC,CAAC,CAAC,qBAuFnB"}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { FlatList, Pressable, View } from "react-native";
2
+ import { FlatList, PanResponder, Pressable, View, } from "react-native";
3
3
  import { cn } from "../utils/cn";
4
4
  import { MutedText, Text } from "./text";
5
5
  import { Skeleton } from "./skeleton";
@@ -31,6 +31,73 @@ export function resolveColumnStyle(column) {
31
31
  }
32
32
  return { ...base, flex: column.flex ?? 1 };
33
33
  }
34
+ /** Below this a cell shows nothing but its own padding. */
35
+ export const MIN_COLUMN_WIDTH = 64;
36
+ /**
37
+ * The web pointer for a draggable boundary.
38
+ *
39
+ * `col-resize` is a CSS cursor react-native-web passes through, and RN's own
40
+ * `ViewStyle` types only the few cursors native supports — so this is typed as
41
+ * a plain style object rather than cast, which keeps the assertion off the
42
+ * component and out of every future reader's way. Native ignores the property.
43
+ */
44
+ const WEB_COL_RESIZE_CURSOR = { cursor: "col-resize" };
45
+ /**
46
+ * Starting widths for a resizable table: the container divided by flex, with
47
+ * fixed-width columns taken out first.
48
+ *
49
+ * Pure so the layout rule is testable without a render host, and so the answer
50
+ * is the same on the first frame as after a resize — a table that measures
51
+ * itself and then computes differently is a table that jumps.
52
+ */
53
+ export function distributeColumnWidths(columns, totalWidth, minWidth = MIN_COLUMN_WIDTH) {
54
+ const fixed = columns.reduce((sum, c) => sum + (typeof c.width === "number" ? c.width : 0), 0);
55
+ const flexColumns = columns.filter((c) => typeof c.width !== "number");
56
+ const flexTotal = flexColumns.reduce((sum, c) => sum + (c.flex ?? 1), 0) || 1;
57
+ // Never negative: a container narrower than its fixed columns would
58
+ // otherwise hand out negative widths and collapse every flexible cell.
59
+ const spare = Math.max(0, totalWidth - fixed);
60
+ return columns.map((c) => typeof c.width === "number"
61
+ ? c.width
62
+ : Math.max(minWidth, (spare * (c.flex ?? 1)) / flexTotal));
63
+ }
64
+ /**
65
+ * Apply one drag to a pair of adjacent columns.
66
+ *
67
+ * Resizing takes width from the NEIGHBOUR rather than from the table, so the
68
+ * total stays put and the columns to the right do not crawl sideways as the
69
+ * handle moves. Both sides clamp at `minWidth`, so a drag past the limit stops
70
+ * instead of inverting the pair.
71
+ */
72
+ export function resizeColumnPair(widths, index, delta, minWidth = MIN_COLUMN_WIDTH) {
73
+ const next = [...widths];
74
+ const left = next[index];
75
+ const right = next[index + 1];
76
+ if (left === undefined || right === undefined) {
77
+ return next;
78
+ }
79
+ const clamped = Math.max(minWidth - left, Math.min(delta, right - minWidth));
80
+ next[index] = left + clamped;
81
+ next[index + 1] = right - clamped;
82
+ return next;
83
+ }
84
+ /**
85
+ * A cell's style, with an explicit width when the table is resizable.
86
+ *
87
+ * Wraps {@link resolveColumnStyle} rather than replacing it: the flex path is
88
+ * still what a non-resizable table uses, and one function deciding padding and
89
+ * alignment keeps the two from drifting apart by a pixel.
90
+ */
91
+ function cellStyle(column, width) {
92
+ const base = resolveColumnStyle(column);
93
+ if (width === undefined) {
94
+ return base;
95
+ }
96
+ // `flex` has to go, not just be overridden: a box with both grows past the
97
+ // width it was told to take.
98
+ const { flex: _flex, ...rest } = base;
99
+ return { ...rest, width };
100
+ }
34
101
  /**
35
102
  * Decide the body mode from the loading flag + row count. Loading wins over
36
103
  * everything; an empty data set (when not loading) shows the empty state.
@@ -42,22 +109,76 @@ export function dataTableBodyMode(loading, rowCount) {
42
109
  }
43
110
  return rowCount === 0 ? "empty" : "data";
44
111
  }
45
- function HeaderRowInner({ columns }) {
112
+ function HeaderRowInner({ columns, widths, onResize, }) {
46
113
  return (<View className={cn("flex-row border-b border-border bg-card dark:border-neutral-800 dark:bg-neutral-900/50")} accessibilityRole="header">
47
- {columns.map((column) => (<View key={column.key} style={resolveColumnStyle(column)}>
114
+ {columns.map((column, i) => (<View key={column.key} style={cellStyle(column, widths?.[i])}
115
+ // `relative` so the handle can sit on this cell's trailing edge; it
116
+ // is absolutely placed and half of it overhangs the boundary, which
117
+ // is what makes the target land where the eye expects.
118
+ className="relative">
48
119
  <Text className={cn("text-xs font-semibold uppercase tracking-wider text-muted-foreground dark:text-neutral-400", alignClass[column.align ?? "left"])} numberOfLines={1}>
49
120
  {column.header}
50
121
  </Text>
122
+ {onResize && i < columns.length - 1 ? (<ColumnResizeHandle onResize={(delta) => onResize(i, delta)}/>) : null}
51
123
  </View>))}
52
124
  </View>);
53
125
  }
126
+ /**
127
+ * The draggable boundary between two header cells.
128
+ *
129
+ * A `PanResponder` rather than a gesture-handler recogniser: this package does
130
+ * not depend on `react-native-gesture-handler`, and a header handle needs no
131
+ * more than "how far has the pointer moved since it went down".
132
+ *
133
+ * `dx` is reported cumulatively from the gesture's start, so each move is fed
134
+ * the DIFFERENCE from the last one — passing `dx` straight through would apply
135
+ * the whole travel again on every frame and the column would run away.
136
+ */
137
+ function ColumnResizeHandle({ onResize }) {
138
+ const last = React.useRef(0);
139
+ const responder = React.useMemo(() => PanResponder.create({
140
+ onStartShouldSetPanResponder: () => true,
141
+ onMoveShouldSetPanResponder: () => true,
142
+ onPanResponderGrant: () => {
143
+ last.current = 0;
144
+ },
145
+ onPanResponderMove: (_event, gesture) => {
146
+ onResize(gesture.dx - last.current);
147
+ last.current = gesture.dx;
148
+ },
149
+ onPanResponderRelease: () => {
150
+ last.current = 0;
151
+ },
152
+ }), [onResize]);
153
+ return (<View {...responder.panHandlers}
154
+ // Wider than it looks: the visible rule is 1px and the target is 9,
155
+ // because a 1px drag target is a 1px drag target.
156
+ style={[
157
+ {
158
+ position: "absolute",
159
+ top: 0,
160
+ bottom: 0,
161
+ right: -4,
162
+ width: 9,
163
+ alignItems: "center",
164
+ },
165
+ // `col-resize` is a WEB cursor and RN's `ViewStyle` only types the
166
+ // handful native supports, so it goes in as its own object rather than
167
+ // widening the whole style to `unknown`. Without it the pointer gives
168
+ // no sign the boundary can be dragged; react-native-web passes it
169
+ // through and native ignores it.
170
+ WEB_COL_RESIZE_CURSOR,
171
+ ]} accessibilityRole="adjustable" accessibilityLabel="Resize column">
172
+ <View className="h-full w-px bg-border dark:bg-neutral-800"/>
173
+ </View>);
174
+ }
54
175
  // Memoized so an unchanged row (stable `columns` + `onPress` identity) skips
55
176
  // re-rendering when the FlatList recycles. `React.memo` on a generic function
56
177
  // erases the type parameter, so we cast back to a generic-preserving signature.
57
178
  const HeaderRow = React.memo(HeaderRowInner);
58
- function DataRowInner({ row, columns, onPress, }) {
179
+ function DataRowInner({ row, columns, widths, onPress, }) {
59
180
  const cells = (<>
60
- {columns.map((column) => (<View key={column.key} style={resolveColumnStyle(column)}>
181
+ {columns.map((column, i) => (<View key={column.key} style={cellStyle(column, widths?.[i])}>
61
182
  {column.render ? (column.render(row)) : (<Text className={cn("text-sm text-foreground", alignClass[column.align ?? "left"])}>
62
183
  {String(row[column.key] ?? "")}
63
184
  </Text>)}
@@ -81,14 +202,46 @@ const DataRow = React.memo(DataRowInner);
81
202
  * `emptyMessage`). Columns size by fixed `width` or `flex`, support custom
82
203
  * `render`, and alignment.
83
204
  */
84
- export function DataTable({ columns, data, keyExtractor, onRowPress, loading = false, loadingRowCount = 5, emptyState, emptyMessage = "No data", className, }) {
205
+ export function DataTable({ columns, data, keyExtractor, onRowPress, loading = false, loadingRowCount = 5, emptyState, emptyMessage = "No data", resizable = false, className, }) {
85
206
  const mode = dataTableBodyMode(loading, data.length);
207
+ // ── Resizable columns ──────────────────────────────────────────────────
208
+ //
209
+ // Widths are held here rather than on each column so a drag moves ONE pair
210
+ // and the table's total width is unchanged. They are seeded from the
211
+ // measured container, so a resizable table still fills its space instead of
212
+ // needing pixel widths written by hand at every call site.
213
+ //
214
+ // A manual drag wins over a re-seed: `touched` stops a window resize from
215
+ // discarding the operator's own column widths, which is what made the first
216
+ // cut feel broken — every layout pass reset them.
217
+ const [tableWidth, setTableWidth] = React.useState(0);
218
+ const [widths, setWidths] = React.useState(null);
219
+ const touched = React.useRef(false);
220
+ const onLayout = React.useCallback((e) => {
221
+ const next = e.nativeEvent.layout.width;
222
+ setTableWidth((prev) => (Math.abs(prev - next) < 1 ? prev : next));
223
+ }, []);
224
+ React.useEffect(() => {
225
+ if (!resizable || tableWidth <= 0 || touched.current) {
226
+ return;
227
+ }
228
+ setWidths(distributeColumnWidths(columns, tableWidth));
229
+ // `columns` is in the deps because adding or removing one has to
230
+ // redistribute; a caller that rebuilds the array every render should
231
+ // memoize it, which every manager in this estate already does for the
232
+ // row-recycling reason below.
233
+ }, [resizable, tableWidth, columns]);
234
+ const handleResize = React.useCallback((index, delta) => {
235
+ touched.current = true;
236
+ setWidths((prev) => (prev ? resizeColumnPair(prev, index, delta) : prev));
237
+ }, []);
238
+ const resolved = resizable ? (widths ?? undefined) : undefined;
86
239
  // Stable `renderItem` identity (only re-created when `columns`/`onRowPress`
87
240
  // change) so the memoized `DataRow` can recycle. `extraData` tells FlatList
88
241
  // to re-render rows when either of those closed-over deps change.
89
- const renderItem = React.useCallback(({ item }) => <DataRow row={item} columns={columns} onPress={onRowPress}/>, [columns, onRowPress]);
90
- return (<View className={cn("overflow-hidden rounded-lg border border-border dark:border-neutral-800", className)}>
91
- <HeaderRow columns={columns}/>
242
+ const renderItem = React.useCallback(({ item }) => (<DataRow row={item} columns={columns} widths={resolved} onPress={onRowPress}/>), [columns, onRowPress, resolved]);
243
+ return (<View onLayout={resizable ? onLayout : undefined} className={cn("overflow-hidden rounded-lg border border-border dark:border-neutral-800", className)}>
244
+ <HeaderRow columns={columns} widths={resolved} onResize={resizable && resolved ? handleResize : undefined}/>
92
245
  {mode === "loading" ? (<View>
93
246
  {Array.from({ length: loadingRowCount }).map((_, i) => (<View key={i} className="flex-row items-center border-b border-border px-3 py-3 dark:border-neutral-800">
94
247
  <Skeleton className="h-4 flex-1"/>
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.jsx","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table.jsx","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ export { Button, IconButton, type ButtonProps } from "./button";
2
2
  export { Card, CardHeader, CardContent, CardFooter, CardTitle, CardDescription, type CardProps, type CardTitleProps, type CardDescriptionProps, } from "./card";
3
3
  export { Checkbox } from "./checkbox";
4
4
  export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuLabel, } from "./context-menu";
5
- export { DataTable, resolveColumnStyle, dataTableBodyMode, type DataTableProps, type DataTableColumn, type DataTableBodyMode, } from "./data-table";
5
+ export { DataTable, resolveColumnStyle, dataTableBodyMode, distributeColumnWidths, resizeColumnPair, MIN_COLUMN_WIDTH, type DataTableProps, type DataTableColumn, type DataTableBodyMode, } from "./data-table";
6
6
  export { Dialog, DialogContent, DialogFooter, DialogButton, ConfirmDialog } from "./dialog";
7
7
  export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator, } from "./dropdown-menu";
8
8
  export { EntropyMark, EntropyByline, ENTROPY_MARK_VIEWBOX, ENTROPY_MARK_ASPECT, ENTROPY_MARK_PATH, ENTROPY_MARK_STEP, type EntropyMarkProps, type EntropyBylineProps, } from "./entropy-mark";
@@ -31,7 +31,7 @@ export { BottomNav, type BottomNavItem, type BottomNavProps } from "./bottom-nav
31
31
  export { ItemIcon, type ItemIconProps } from "./item-icon";
32
32
  export { TotpDisplay, type TotpDisplayProps } from "./totp-display";
33
33
  export { UserAvatar, type UserAvatarProps } from "./user-avatar";
34
- export { SocialConnections, visibleProviders, type SocialConnectionsProps, type Provider, type ProviderKey, type ProviderVisibility, } from "./social-connections";
34
+ export { SocialConnections, visibleProviders, customIcon, type SocialConnectionsProps, type Provider, type ProviderKey, type ProviderVisibility, type CustomProvider, } from "./social-connections";
35
35
  export { ProfileDialog, ProfileTab, SecurityTab, type ProfileDialogProps, type ProfileTabProps, type SecurityTabProps, } from "./profile";
36
36
  export { ServerSettings, type ServerSettingsProps } from "./server-settings";
37
37
  export { ConnectionSettings, type ConnectionSettingsProps, type RunMode, } from "./connection-settings";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ export { Button, IconButton } from "./button";
4
4
  export { Card, CardHeader, CardContent, CardFooter, CardTitle, CardDescription, } from "./card";
5
5
  export { Checkbox } from "./checkbox";
6
6
  export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuLabel, } from "./context-menu";
7
- export { DataTable, resolveColumnStyle, dataTableBodyMode, } from "./data-table";
7
+ export { DataTable, resolveColumnStyle, dataTableBodyMode, distributeColumnWidths, resizeColumnPair, MIN_COLUMN_WIDTH, } from "./data-table";
8
8
  export { Dialog, DialogContent, DialogFooter, DialogButton, ConfirmDialog } from "./dialog";
9
9
  export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator, } from "./dropdown-menu";
10
10
  export { EntropyMark, EntropyByline, ENTROPY_MARK_VIEWBOX, ENTROPY_MARK_ASPECT, ENTROPY_MARK_PATH, ENTROPY_MARK_STEP, } from "./entropy-mark";
@@ -33,7 +33,7 @@ export { BottomNav } from "./bottom-nav";
33
33
  export { ItemIcon } from "./item-icon";
34
34
  export { TotpDisplay } from "./totp-display";
35
35
  export { UserAvatar } from "./user-avatar";
36
- export { SocialConnections, visibleProviders, } from "./social-connections";
36
+ export { SocialConnections, visibleProviders, customIcon, } from "./social-connections";
37
37
  export { ProfileDialog, ProfileTab, SecurityTab, } from "./profile";
38
38
  export { ServerSettings } from "./server-settings";
39
39
  export { ConnectionSettings, } from "./connection-settings";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,uDAAuD;AAEvD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAoB,MAAM,UAAU,CAAC;AAEhE,OAAO,EACL,IAAI,EACJ,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,eAAe,GAIhB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,GAIjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE5F,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,GAGlB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAA+B,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAiC,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAA2B,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAAE,qBAAqB,EAAmC,MAAM,2BAA2B,CAAC;AAEnG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAmB,MAAM,SAAS,CAAC;AAEnG,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAyB,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GAMrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EACL,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,WAAW,EACX,eAAe,GAGhB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAsC,MAAM,aAAa,CAAC;AAE5F,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAkB,MAAM,QAAQ,CAAC;AAE9F,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAyB,MAAM,QAAQ,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAqB,MAAM,YAAY,CAAC;AAEnE,OAAO,EAAE,SAAS,EAA2C,MAAM,cAAc,CAAC;AAElF,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAyB,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAwB,MAAM,eAAe,CAAC;AAEjE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,GAMX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,aAAa,EACb,UAAU,EACV,WAAW,GAIZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,cAAc,EAA4B,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EACL,kBAAkB,GAGnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAA+B,MAAM,sBAAsB,CAAC;AAEtF,OAAO,EAAE,cAAc,EAA4C,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAE,MAAM,EAAoB,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,WAAW,EAAyB,MAAM,gBAAgB,CAAC"}
@@ -51,6 +51,46 @@ export interface SocialConnectionsProps {
51
51
  showGoogle?: boolean;
52
52
  /** Whether to offer "Continue with Microsoft". Defaults to `true`. See {@link SocialConnectionsProps.showApple}. */
53
53
  showMicrosoft?: boolean;
54
+ /**
55
+ * Providers this component has no brand mark for, rendered after the four it
56
+ * does — Okta, Keycloak, GitHub, another Access instance, anything an
57
+ * operator configures.
58
+ *
59
+ * ## Why these are a caller-supplied list rather than more `ProviderKey`s
60
+ *
61
+ * The four above are a closed set with bundled glyphs and a fixed order, so
62
+ * they can be named in the type. What an operator connects is open: adding a
63
+ * key here for every provider anyone might configure is a release of this
64
+ * package per connector, and the whole point of the identity provider's
65
+ * connector table is that it does not need one.
66
+ *
67
+ * Ordered as given, after the built-ins, so the row is stable — the
68
+ * built-ins keep the positions users have learned and new connectors append.
69
+ *
70
+ * `iconUrl` is optional and points at whatever the operator supplied. Absent,
71
+ * unreachable, or malformed, the button falls back to a neutral glyph rather
72
+ * than an empty square: a connector with no icon must still be pressable and
73
+ * still be labelled.
74
+ */
75
+ custom?: readonly CustomProvider[];
76
+ }
77
+ /**
78
+ * A provider this package does not ship a mark for.
79
+ *
80
+ * `key` only has to be unique within the row; it is not a {@link ProviderKey}
81
+ * and is never matched against one. Prefix collisions with the built-ins are
82
+ * impossible because the rendered React keys are namespaced.
83
+ */
84
+ export interface CustomProvider {
85
+ key: string;
86
+ /** What the tooltip and the screen reader say: "Continue with {label}". */
87
+ label: string;
88
+ /**
89
+ * Absolute URL of the provider's mark. Rendered at 22px square, matching the
90
+ * bundled glyphs.
91
+ */
92
+ iconUrl?: string | null;
93
+ onPress?: () => void;
54
94
  }
55
95
  /** The federated providers this row can draw. */
56
96
  export type ProviderKey = "entropy" | "apple" | "google" | "microsoft";
@@ -74,6 +114,25 @@ export type ProviderVisibility = Record<ProviderKey, boolean>;
74
114
  * reshuffle between renders or between consumers.
75
115
  */
76
116
  export declare function visibleProviders(shown: ProviderVisibility): readonly Provider[];
117
+ /**
118
+ * What a caller-supplied provider's button should draw.
119
+ *
120
+ * Pure, exported and separate from the component for the same reason
121
+ * {@link visibleProviders} is: the fallback rule is the part worth testing, and
122
+ * the component pulls in `@expo/vector-icons` and reanimated, which the unit
123
+ * suite's transform does not process.
124
+ *
125
+ * A blank or whitespace-only URL counts as absent, not as a URL to fetch: an
126
+ * operator who clears the field in a form leaves `""` behind far more often
127
+ * than `null`, and `<Image source={{uri: ""}}>` is a request that fails
128
+ * silently on web and renders an empty square on native.
129
+ */
130
+ export declare function customIcon(iconUrl: string | null | undefined, failed: boolean): {
131
+ kind: "image";
132
+ uri: string;
133
+ } | {
134
+ kind: "fallback";
135
+ };
77
136
  /**
78
137
  * Button row for federated sign-in: Entropy / Apple / Google / Microsoft.
79
138
  *
@@ -94,6 +153,6 @@ export declare function visibleProviders(shown: ProviderVisibility): readonly Pr
94
153
  * reader announces. Without the tooltip these are four unlabelled squares, and
95
154
  * a user has to guess which mark is which.
96
155
  */
97
- export declare function SocialConnections({ onApple, onGoogle, onMicrosoft, onEntropy, showEntropy, showApple, showGoogle, showMicrosoft, }: SocialConnectionsProps): React.JSX.Element;
156
+ export declare function SocialConnections({ onApple, onGoogle, onMicrosoft, onEntropy, showEntropy, showApple, showGoogle, showMicrosoft, custom, }: SocialConnectionsProps): React.JSX.Element;
98
157
  export default SocialConnections;
99
158
  //# sourceMappingURL=social-connections.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"social-connections.d.ts","sourceRoot":"","sources":["../../src/components/social-connections.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iHAAiH;IACjH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oHAAoH;IACpH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,WAAW,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAAC;CAC9D;AAYD;8EAC8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,kBAAkB,GACxB,SAAS,QAAQ,EAAE,CAErB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,WAAW,EACX,SAAS,EACT,WAAkB,EAClB,SAAgB,EAChB,UAAiB,EACjB,aAAoB,GACrB,EAAE,sBAAsB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAoD5C;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"social-connections.d.ts","sourceRoot":"","sources":["../../src/components/social-connections.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iHAAiH;IACjH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oHAAoH;IACpH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,WAAW,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAAC;CAC9D;AAYD;8EAC8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,kBAAkB,GACxB,SAAS,QAAQ,EAAE,CAErB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,MAAM,EAAE,OAAO,GACd;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAMvD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,WAAW,EACX,SAAS,EACT,WAAkB,EAClB,SAAgB,EAChB,UAAiB,EACjB,aAAoB,EACpB,MAAW,GACZ,EAAE,sBAAsB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA6D5C;AAqDD,eAAe,iBAAiB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Pressable, View } from "react-native";
2
+ import { Image, Pressable, View } from "react-native";
3
3
  import { Ionicons } from "@expo/vector-icons";
4
4
  import { useColorScheme } from "nativewind";
5
5
  import { EntropyMark } from "./entropy-mark";
@@ -26,6 +26,26 @@ const PROVIDERS = [
26
26
  export function visibleProviders(shown) {
27
27
  return PROVIDERS.filter(({ key }) => shown[key]);
28
28
  }
29
+ /**
30
+ * What a caller-supplied provider's button should draw.
31
+ *
32
+ * Pure, exported and separate from the component for the same reason
33
+ * {@link visibleProviders} is: the fallback rule is the part worth testing, and
34
+ * the component pulls in `@expo/vector-icons` and reanimated, which the unit
35
+ * suite's transform does not process.
36
+ *
37
+ * A blank or whitespace-only URL counts as absent, not as a URL to fetch: an
38
+ * operator who clears the field in a form leaves `""` behind far more often
39
+ * than `null`, and `<Image source={{uri: ""}}>` is a request that fails
40
+ * silently on web and renders an empty square on native.
41
+ */
42
+ export function customIcon(iconUrl, failed) {
43
+ const uri = iconUrl?.trim();
44
+ if (!uri || failed) {
45
+ return { kind: "fallback" };
46
+ }
47
+ return { kind: "image", uri };
48
+ }
29
49
  /**
30
50
  * Button row for federated sign-in: Entropy / Apple / Google / Microsoft.
31
51
  *
@@ -46,7 +66,7 @@ export function visibleProviders(shown) {
46
66
  * reader announces. Without the tooltip these are four unlabelled squares, and
47
67
  * a user has to guess which mark is which.
48
68
  */
49
- export function SocialConnections({ onApple, onGoogle, onMicrosoft, onEntropy, showEntropy = true, showApple = true, showGoogle = true, showMicrosoft = true, }) {
69
+ export function SocialConnections({ onApple, onGoogle, onMicrosoft, onEntropy, showEntropy = true, showApple = true, showGoogle = true, showMicrosoft = true, custom = [], }) {
50
70
  const { colorScheme } = useColorScheme();
51
71
  const isDark = colorScheme === "dark";
52
72
  const handlers = {
@@ -80,7 +100,39 @@ export function SocialConnections({ onApple, onGoogle, onMicrosoft, onEntropy, s
80
100
  </TooltipTrigger>
81
101
  <TooltipContent>{`Continue with ${label}`}</TooltipContent>
82
102
  </Tooltip>))}
103
+ {custom.map((provider) => (<CustomProviderButton
104
+ // Namespaced so a caller's key cannot collide with a built-in's and
105
+ // silently replace it in the reconciler.
106
+ key={`custom:${provider.key}`} provider={provider} isDark={isDark}/>))}
83
107
  </View>);
84
108
  }
109
+ /**
110
+ * One caller-supplied provider.
111
+ *
112
+ * Its own component because it holds state the built-ins do not: whether the
113
+ * remote icon failed. A broken URL has to degrade to the neutral glyph, and
114
+ * `onError` can only be observed per image.
115
+ */
116
+ function CustomProviderButton({ provider, isDark, }) {
117
+ const [iconFailed, setIconFailed] = React.useState(false);
118
+ const tint = isDark ? "#FFFFFF" : "#000000";
119
+ const icon = customIcon(provider.iconUrl, iconFailed);
120
+ return (<Tooltip delayDuration={200}>
121
+ <TooltipTrigger asChild>
122
+ <Pressable onPress={provider.onPress} className="h-12 w-12 items-center justify-center rounded-lg border border-border dark:border-neutral-600 active:opacity-70" accessibilityRole="button" accessibilityLabel={`Continue with ${provider.label}`}>
123
+ {icon.kind === "image" ? (<Image source={{ uri: icon.uri }} style={{ width: 22, height: 22 }}
124
+ // `contain` rather than `cover`: an operator's mark is whatever
125
+ // aspect ratio they have, and cropping somebody's logo to a
126
+ // square is worse than letterboxing it.
127
+ resizeMode="contain" onError={() => setIconFailed(true)} accessibilityIgnoresInvertColors/>) : (
128
+ // The neutral fallback. A key rather than a globe or a puzzle
129
+ // piece: this is a sign-in credential, and the glyph should say so
130
+ // without implying a vendor.
131
+ <Ionicons name="key-outline" size={22} color={tint}/>)}
132
+ </Pressable>
133
+ </TooltipTrigger>
134
+ <TooltipContent>{`Continue with ${provider.label}`}</TooltipContent>
135
+ </Tooltip>);
136
+ }
85
137
  export default SocialConnections;
86
138
  //# sourceMappingURL=social-connections.jsx.map
@@ -1 +1 @@
1
- {"version":3,"file":"social-connections.jsx","sourceRoot":"","sources":["../../src/components/social-connections.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"social-connections.jsx","sourceRoot":"","sources":["../../src/components/social-connections.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entropy-softworks/ui",
3
- "version": "2026.910.2",
3
+ "version": "2026.911.1",
4
4
  "private": false,
5
5
  "description": "Shared React Native UI primitives, auth screens, hooks, and services for Entropy Softworks Expo apps",
6
6
  "license": "MIT",
@@ -1,4 +1,11 @@
1
- import { resolveColumnStyle, dataTableBodyMode, type DataTableColumn } from "../data-table";
1
+ import {
2
+ resolveColumnStyle,
3
+ dataTableBodyMode,
4
+ distributeColumnWidths,
5
+ resizeColumnPair,
6
+ MIN_COLUMN_WIDTH,
7
+ type DataTableColumn,
8
+ } from "../data-table";
2
9
 
3
10
  // The component module pulls in `react-native-reanimated` (via Skeleton),
4
11
  // which ships ESM that the unit-suite babel transform does not process. The
@@ -92,3 +99,65 @@ describe("DataTable column rendering", () => {
92
99
  expect(out).toBe("SAM");
93
100
  });
94
101
  });
102
+
103
+ describe("distributeColumnWidths", () => {
104
+ const cols = [
105
+ { key: "a", header: "A" },
106
+ { key: "b", header: "B" },
107
+ ];
108
+
109
+ it("divides the container by flex so the table fills its space", () => {
110
+ expect(distributeColumnWidths(cols, 600)).toEqual([300, 300]);
111
+ });
112
+
113
+ it("weights by each column's flex", () => {
114
+ const weighted = [
115
+ { key: "a", header: "A", flex: 3 },
116
+ { key: "b", header: "B", flex: 1 },
117
+ ];
118
+ expect(distributeColumnWidths(weighted, 800)).toEqual([600, 200]);
119
+ });
120
+
121
+ it("takes fixed widths out before dividing the rest", () => {
122
+ const mixed = [
123
+ { key: "a", header: "A", width: 100 },
124
+ { key: "b", header: "B" },
125
+ { key: "c", header: "C" },
126
+ ];
127
+ expect(distributeColumnWidths(mixed, 500)).toEqual([100, 200, 200]);
128
+ });
129
+
130
+ it("never hands out less than the minimum, or a negative", () => {
131
+ // A container narrower than its fixed columns: the flexible ones would
132
+ // otherwise get negative widths and collapse every cell in the row.
133
+ const mixed = [
134
+ { key: "a", header: "A", width: 400 },
135
+ { key: "b", header: "B" },
136
+ ];
137
+ expect(distributeColumnWidths(mixed, 100)).toEqual([400, MIN_COLUMN_WIDTH]);
138
+ });
139
+ });
140
+
141
+ describe("resizeColumnPair", () => {
142
+ it("moves width from the neighbour, leaving the total alone", () => {
143
+ const before = [200, 200, 200];
144
+ const after = resizeColumnPair(before, 0, 40);
145
+ expect(after).toEqual([240, 160, 200]);
146
+ // The property that matters: dragging a boundary must not change how wide
147
+ // the table is, or every column to the right crawls sideways.
148
+ expect(after.reduce((a, b) => a + b, 0)).toBe(
149
+ before.reduce((a, b) => a + b, 0)
150
+ );
151
+ });
152
+
153
+ it("stops at the minimum rather than inverting the pair", () => {
154
+ const after = resizeColumnPair([100, 100], 0, 500);
155
+ expect(after).toEqual([200 - MIN_COLUMN_WIDTH, MIN_COLUMN_WIDTH]);
156
+ const back = resizeColumnPair([100, 100], 0, -500);
157
+ expect(back).toEqual([MIN_COLUMN_WIDTH, 200 - MIN_COLUMN_WIDTH]);
158
+ });
159
+
160
+ it("is a no-op past the last boundary", () => {
161
+ expect(resizeColumnPair([100, 100], 1, 20)).toEqual([100, 100]);
162
+ });
163
+ });
@@ -1,4 +1,5 @@
1
1
  import {
2
+ customIcon,
2
3
  visibleProviders,
3
4
  type ProviderKey,
4
5
  type ProviderVisibility,
@@ -95,3 +96,37 @@ describe("visibleProviders", () => {
95
96
  expect(byKey.get("microsoft")?.icon).toBe("logo-microsoft");
96
97
  });
97
98
  });
99
+
100
+ describe("customIcon", () => {
101
+ it("uses the operator's URL when there is one", () => {
102
+ expect(customIcon("https://cdn.example/okta.svg", false)).toEqual({
103
+ kind: "image",
104
+ uri: "https://cdn.example/okta.svg",
105
+ });
106
+ });
107
+
108
+ it("trims, because a pasted URL usually arrives with whitespace", () => {
109
+ expect(customIcon(" https://cdn.example/k.png\n", false)).toEqual({
110
+ kind: "image",
111
+ uri: "https://cdn.example/k.png",
112
+ });
113
+ });
114
+
115
+ it.each([undefined, null, "", " "])(
116
+ "falls back when the URL is %p",
117
+ (value) => {
118
+ // A blank string is the case that matters: clearing a form field leaves
119
+ // "" far more often than null, and `<Image source={{uri: ""}}>` renders
120
+ // an empty square rather than failing loudly.
121
+ expect(customIcon(value, false)).toEqual({ kind: "fallback" });
122
+ }
123
+ );
124
+
125
+ it("falls back once the image has failed, URL or not", () => {
126
+ // An unreachable or malformed URL must still leave a pressable, labelled
127
+ // button — a connector the operator can see and use.
128
+ expect(customIcon("https://cdn.example/gone.png", true)).toEqual({
129
+ kind: "fallback",
130
+ });
131
+ });
132
+ });
@@ -1,5 +1,13 @@
1
1
  import React from "react";
2
- import { FlatList, Pressable, View, type ListRenderItem, type ViewStyle } from "react-native";
2
+ import {
3
+ FlatList,
4
+ PanResponder,
5
+ Pressable,
6
+ View,
7
+ type LayoutChangeEvent,
8
+ type ListRenderItem,
9
+ type ViewStyle,
10
+ } from "react-native";
3
11
  import { cn } from "../utils/cn";
4
12
  import { MutedText, Text } from "./text";
5
13
  import { Skeleton } from "./skeleton";
@@ -34,6 +42,20 @@ export interface DataTableProps<T> {
34
42
  emptyState?: React.ReactNode;
35
43
  /** Fallback empty message when `emptyState` is not provided. */
36
44
  emptyMessage?: string;
45
+ /**
46
+ * Let the operator drag the boundary between two columns.
47
+ *
48
+ * Off by default, because it costs a measured container and per-column
49
+ * width state — a table that never needs it should not pay for it. On, the
50
+ * columns start at their `flex` share of the measured width (so the table
51
+ * still fills its space) and a drag moves width between the pair either
52
+ * side of the handle rather than growing the table.
53
+ *
54
+ * Web-oriented: the handles are 8px targets suited to a pointer. They
55
+ * render on native too and work, but a phone is not where a column gets
56
+ * dragged.
57
+ */
58
+ resizable?: boolean;
37
59
  className?: string;
38
60
  }
39
61
 
@@ -71,6 +93,92 @@ export function resolveColumnStyle<T>(column: DataTableColumn<T>): ViewStyle {
71
93
  return { ...base, flex: column.flex ?? 1 };
72
94
  }
73
95
 
96
+ /** Below this a cell shows nothing but its own padding. */
97
+ export const MIN_COLUMN_WIDTH = 64;
98
+
99
+ /**
100
+ * The web pointer for a draggable boundary.
101
+ *
102
+ * `col-resize` is a CSS cursor react-native-web passes through, and RN's own
103
+ * `ViewStyle` types only the few cursors native supports — so this is typed as
104
+ * a plain style object rather than cast, which keeps the assertion off the
105
+ * component and out of every future reader's way. Native ignores the property.
106
+ */
107
+ const WEB_COL_RESIZE_CURSOR = { cursor: "col-resize" } as unknown as ViewStyle;
108
+
109
+ /**
110
+ * Starting widths for a resizable table: the container divided by flex, with
111
+ * fixed-width columns taken out first.
112
+ *
113
+ * Pure so the layout rule is testable without a render host, and so the answer
114
+ * is the same on the first frame as after a resize — a table that measures
115
+ * itself and then computes differently is a table that jumps.
116
+ */
117
+ export function distributeColumnWidths<T>(
118
+ columns: DataTableColumn<T>[],
119
+ totalWidth: number,
120
+ minWidth = MIN_COLUMN_WIDTH
121
+ ): number[] {
122
+ const fixed = columns.reduce(
123
+ (sum, c) => sum + (typeof c.width === "number" ? c.width : 0),
124
+ 0
125
+ );
126
+ const flexColumns = columns.filter((c) => typeof c.width !== "number");
127
+ const flexTotal = flexColumns.reduce((sum, c) => sum + (c.flex ?? 1), 0) || 1;
128
+ // Never negative: a container narrower than its fixed columns would
129
+ // otherwise hand out negative widths and collapse every flexible cell.
130
+ const spare = Math.max(0, totalWidth - fixed);
131
+ return columns.map((c) =>
132
+ typeof c.width === "number"
133
+ ? c.width
134
+ : Math.max(minWidth, (spare * (c.flex ?? 1)) / flexTotal)
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Apply one drag to a pair of adjacent columns.
140
+ *
141
+ * Resizing takes width from the NEIGHBOUR rather than from the table, so the
142
+ * total stays put and the columns to the right do not crawl sideways as the
143
+ * handle moves. Both sides clamp at `minWidth`, so a drag past the limit stops
144
+ * instead of inverting the pair.
145
+ */
146
+ export function resizeColumnPair(
147
+ widths: number[],
148
+ index: number,
149
+ delta: number,
150
+ minWidth = MIN_COLUMN_WIDTH
151
+ ): number[] {
152
+ const next = [...widths];
153
+ const left = next[index];
154
+ const right = next[index + 1];
155
+ if (left === undefined || right === undefined) {
156
+ return next;
157
+ }
158
+ const clamped = Math.max(minWidth - left, Math.min(delta, right - minWidth));
159
+ next[index] = left + clamped;
160
+ next[index + 1] = right - clamped;
161
+ return next;
162
+ }
163
+
164
+ /**
165
+ * A cell's style, with an explicit width when the table is resizable.
166
+ *
167
+ * Wraps {@link resolveColumnStyle} rather than replacing it: the flex path is
168
+ * still what a non-resizable table uses, and one function deciding padding and
169
+ * alignment keeps the two from drifting apart by a pixel.
170
+ */
171
+ function cellStyle<T>(column: DataTableColumn<T>, width?: number): ViewStyle {
172
+ const base = resolveColumnStyle(column);
173
+ if (width === undefined) {
174
+ return base;
175
+ }
176
+ // `flex` has to go, not just be overridden: a box with both grows past the
177
+ // width it was told to take.
178
+ const { flex: _flex, ...rest } = base;
179
+ return { ...rest, width };
180
+ }
181
+
74
182
  /** Which body the table renders: skeleton rows, an empty placeholder, or data. */
75
183
  export type DataTableBodyMode = "loading" | "empty" | "data";
76
184
 
@@ -86,7 +194,16 @@ export function dataTableBodyMode(loading: boolean, rowCount: number): DataTable
86
194
  return rowCount === 0 ? "empty" : "data";
87
195
  }
88
196
 
89
- function HeaderRowInner<T>({ columns }: { columns: DataTableColumn<T>[] }) {
197
+ function HeaderRowInner<T>({
198
+ columns,
199
+ widths,
200
+ onResize,
201
+ }: {
202
+ columns: DataTableColumn<T>[];
203
+ /** Resolved pixel widths, when the table is resizable. */
204
+ widths?: number[];
205
+ onResize?: (index: number, delta: number) => void;
206
+ }) {
90
207
  return (
91
208
  <View
92
209
  className={cn(
@@ -94,8 +211,15 @@ function HeaderRowInner<T>({ columns }: { columns: DataTableColumn<T>[] }) {
94
211
  )}
95
212
  accessibilityRole="header"
96
213
  >
97
- {columns.map((column) => (
98
- <View key={column.key} style={resolveColumnStyle(column)}>
214
+ {columns.map((column, i) => (
215
+ <View
216
+ key={column.key}
217
+ style={cellStyle(column, widths?.[i])}
218
+ // `relative` so the handle can sit on this cell's trailing edge; it
219
+ // is absolutely placed and half of it overhangs the boundary, which
220
+ // is what makes the target land where the eye expects.
221
+ className="relative"
222
+ >
99
223
  <Text
100
224
  className={cn(
101
225
  "text-xs font-semibold uppercase tracking-wider text-muted-foreground dark:text-neutral-400",
@@ -105,12 +229,76 @@ function HeaderRowInner<T>({ columns }: { columns: DataTableColumn<T>[] }) {
105
229
  >
106
230
  {column.header}
107
231
  </Text>
232
+ {onResize && i < columns.length - 1 ? (
233
+ <ColumnResizeHandle onResize={(delta) => onResize(i, delta)} />
234
+ ) : null}
108
235
  </View>
109
236
  ))}
110
237
  </View>
111
238
  );
112
239
  }
113
240
 
241
+ /**
242
+ * The draggable boundary between two header cells.
243
+ *
244
+ * A `PanResponder` rather than a gesture-handler recogniser: this package does
245
+ * not depend on `react-native-gesture-handler`, and a header handle needs no
246
+ * more than "how far has the pointer moved since it went down".
247
+ *
248
+ * `dx` is reported cumulatively from the gesture's start, so each move is fed
249
+ * the DIFFERENCE from the last one — passing `dx` straight through would apply
250
+ * the whole travel again on every frame and the column would run away.
251
+ */
252
+ function ColumnResizeHandle({ onResize }: { onResize: (delta: number) => void }) {
253
+ const last = React.useRef(0);
254
+ const responder = React.useMemo(
255
+ () =>
256
+ PanResponder.create({
257
+ onStartShouldSetPanResponder: () => true,
258
+ onMoveShouldSetPanResponder: () => true,
259
+ onPanResponderGrant: () => {
260
+ last.current = 0;
261
+ },
262
+ onPanResponderMove: (_event, gesture) => {
263
+ onResize(gesture.dx - last.current);
264
+ last.current = gesture.dx;
265
+ },
266
+ onPanResponderRelease: () => {
267
+ last.current = 0;
268
+ },
269
+ }),
270
+ [onResize]
271
+ );
272
+
273
+ return (
274
+ <View
275
+ {...responder.panHandlers}
276
+ // Wider than it looks: the visible rule is 1px and the target is 9,
277
+ // because a 1px drag target is a 1px drag target.
278
+ style={[
279
+ {
280
+ position: "absolute",
281
+ top: 0,
282
+ bottom: 0,
283
+ right: -4,
284
+ width: 9,
285
+ alignItems: "center",
286
+ },
287
+ // `col-resize` is a WEB cursor and RN's `ViewStyle` only types the
288
+ // handful native supports, so it goes in as its own object rather than
289
+ // widening the whole style to `unknown`. Without it the pointer gives
290
+ // no sign the boundary can be dragged; react-native-web passes it
291
+ // through and native ignores it.
292
+ WEB_COL_RESIZE_CURSOR,
293
+ ]}
294
+ accessibilityRole="adjustable"
295
+ accessibilityLabel="Resize column"
296
+ >
297
+ <View className="h-full w-px bg-border dark:bg-neutral-800" />
298
+ </View>
299
+ );
300
+ }
301
+
114
302
  // Memoized so an unchanged row (stable `columns` + `onPress` identity) skips
115
303
  // re-rendering when the FlatList recycles. `React.memo` on a generic function
116
304
  // erases the type parameter, so we cast back to a generic-preserving signature.
@@ -119,16 +307,18 @@ const HeaderRow = React.memo(HeaderRowInner) as typeof HeaderRowInner;
119
307
  function DataRowInner<T>({
120
308
  row,
121
309
  columns,
310
+ widths,
122
311
  onPress,
123
312
  }: {
124
313
  row: T;
125
314
  columns: DataTableColumn<T>[];
315
+ widths?: number[];
126
316
  onPress?: (row: T) => void;
127
317
  }) {
128
318
  const cells = (
129
319
  <>
130
- {columns.map((column) => (
131
- <View key={column.key} style={resolveColumnStyle(column)}>
320
+ {columns.map((column, i) => (
321
+ <View key={column.key} style={cellStyle(column, widths?.[i])}>
132
322
  {column.render ? (
133
323
  column.render(row)
134
324
  ) : (
@@ -177,24 +367,70 @@ export function DataTable<T>({
177
367
  loadingRowCount = 5,
178
368
  emptyState,
179
369
  emptyMessage = "No data",
370
+ resizable = false,
180
371
  className,
181
372
  }: DataTableProps<T>) {
182
373
  const mode = dataTableBodyMode(loading, data.length);
374
+
375
+ // ── Resizable columns ──────────────────────────────────────────────────
376
+ //
377
+ // Widths are held here rather than on each column so a drag moves ONE pair
378
+ // and the table's total width is unchanged. They are seeded from the
379
+ // measured container, so a resizable table still fills its space instead of
380
+ // needing pixel widths written by hand at every call site.
381
+ //
382
+ // A manual drag wins over a re-seed: `touched` stops a window resize from
383
+ // discarding the operator's own column widths, which is what made the first
384
+ // cut feel broken — every layout pass reset them.
385
+ const [tableWidth, setTableWidth] = React.useState(0);
386
+ const [widths, setWidths] = React.useState<number[] | null>(null);
387
+ const touched = React.useRef(false);
388
+
389
+ const onLayout = React.useCallback((e: LayoutChangeEvent) => {
390
+ const next = e.nativeEvent.layout.width;
391
+ setTableWidth((prev) => (Math.abs(prev - next) < 1 ? prev : next));
392
+ }, []);
393
+
394
+ React.useEffect(() => {
395
+ if (!resizable || tableWidth <= 0 || touched.current) {
396
+ return;
397
+ }
398
+ setWidths(distributeColumnWidths(columns, tableWidth));
399
+ // `columns` is in the deps because adding or removing one has to
400
+ // redistribute; a caller that rebuilds the array every render should
401
+ // memoize it, which every manager in this estate already does for the
402
+ // row-recycling reason below.
403
+ }, [resizable, tableWidth, columns]);
404
+
405
+ const handleResize = React.useCallback((index: number, delta: number) => {
406
+ touched.current = true;
407
+ setWidths((prev) => (prev ? resizeColumnPair(prev, index, delta) : prev));
408
+ }, []);
409
+
410
+ const resolved = resizable ? (widths ?? undefined) : undefined;
411
+
183
412
  // Stable `renderItem` identity (only re-created when `columns`/`onRowPress`
184
413
  // change) so the memoized `DataRow` can recycle. `extraData` tells FlatList
185
414
  // to re-render rows when either of those closed-over deps change.
186
415
  const renderItem = React.useCallback<ListRenderItem<T>>(
187
- ({ item }) => <DataRow row={item} columns={columns} onPress={onRowPress} />,
188
- [columns, onRowPress]
416
+ ({ item }) => (
417
+ <DataRow row={item} columns={columns} widths={resolved} onPress={onRowPress} />
418
+ ),
419
+ [columns, onRowPress, resolved]
189
420
  );
190
421
  return (
191
422
  <View
423
+ onLayout={resizable ? onLayout : undefined}
192
424
  className={cn(
193
425
  "overflow-hidden rounded-lg border border-border dark:border-neutral-800",
194
426
  className
195
427
  )}
196
428
  >
197
- <HeaderRow columns={columns} />
429
+ <HeaderRow
430
+ columns={columns}
431
+ widths={resolved}
432
+ onResize={resizable && resolved ? handleResize : undefined}
433
+ />
198
434
  {mode === "loading" ? (
199
435
  <View>
200
436
  {Array.from({ length: loadingRowCount }).map((_, i) => (
@@ -30,6 +30,9 @@ export {
30
30
  DataTable,
31
31
  resolveColumnStyle,
32
32
  dataTableBodyMode,
33
+ distributeColumnWidths,
34
+ resizeColumnPair,
35
+ MIN_COLUMN_WIDTH,
33
36
  type DataTableProps,
34
37
  type DataTableColumn,
35
38
  type DataTableBodyMode,
@@ -132,10 +135,12 @@ export { UserAvatar, type UserAvatarProps } from "./user-avatar";
132
135
  export {
133
136
  SocialConnections,
134
137
  visibleProviders,
138
+ customIcon,
135
139
  type SocialConnectionsProps,
136
140
  type Provider,
137
141
  type ProviderKey,
138
142
  type ProviderVisibility,
143
+ type CustomProvider,
139
144
  } from "./social-connections";
140
145
 
141
146
  export {
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Pressable, View } from "react-native";
2
+ import { Image, Pressable, View } from "react-native";
3
3
  import { Ionicons } from "@expo/vector-icons";
4
4
  import { useColorScheme } from "nativewind";
5
5
  import { EntropyMark } from "./entropy-mark";
@@ -57,6 +57,47 @@ export interface SocialConnectionsProps {
57
57
  showGoogle?: boolean;
58
58
  /** Whether to offer "Continue with Microsoft". Defaults to `true`. See {@link SocialConnectionsProps.showApple}. */
59
59
  showMicrosoft?: boolean;
60
+ /**
61
+ * Providers this component has no brand mark for, rendered after the four it
62
+ * does — Okta, Keycloak, GitHub, another Access instance, anything an
63
+ * operator configures.
64
+ *
65
+ * ## Why these are a caller-supplied list rather than more `ProviderKey`s
66
+ *
67
+ * The four above are a closed set with bundled glyphs and a fixed order, so
68
+ * they can be named in the type. What an operator connects is open: adding a
69
+ * key here for every provider anyone might configure is a release of this
70
+ * package per connector, and the whole point of the identity provider's
71
+ * connector table is that it does not need one.
72
+ *
73
+ * Ordered as given, after the built-ins, so the row is stable — the
74
+ * built-ins keep the positions users have learned and new connectors append.
75
+ *
76
+ * `iconUrl` is optional and points at whatever the operator supplied. Absent,
77
+ * unreachable, or malformed, the button falls back to a neutral glyph rather
78
+ * than an empty square: a connector with no icon must still be pressable and
79
+ * still be labelled.
80
+ */
81
+ custom?: readonly CustomProvider[];
82
+ }
83
+
84
+ /**
85
+ * A provider this package does not ship a mark for.
86
+ *
87
+ * `key` only has to be unique within the row; it is not a {@link ProviderKey}
88
+ * and is never matched against one. Prefix collisions with the built-ins are
89
+ * impossible because the rendered React keys are namespaced.
90
+ */
91
+ export interface CustomProvider {
92
+ key: string;
93
+ /** What the tooltip and the screen reader say: "Continue with {label}". */
94
+ label: string;
95
+ /**
96
+ * Absolute URL of the provider's mark. Rendered at 22px square, matching the
97
+ * bundled glyphs.
98
+ */
99
+ iconUrl?: string | null;
100
+ onPress?: () => void;
60
101
  }
61
102
 
62
103
  /** The federated providers this row can draw. */
@@ -99,6 +140,30 @@ export function visibleProviders(
99
140
  return PROVIDERS.filter(({ key }) => shown[key]);
100
141
  }
101
142
 
143
+ /**
144
+ * What a caller-supplied provider's button should draw.
145
+ *
146
+ * Pure, exported and separate from the component for the same reason
147
+ * {@link visibleProviders} is: the fallback rule is the part worth testing, and
148
+ * the component pulls in `@expo/vector-icons` and reanimated, which the unit
149
+ * suite's transform does not process.
150
+ *
151
+ * A blank or whitespace-only URL counts as absent, not as a URL to fetch: an
152
+ * operator who clears the field in a form leaves `""` behind far more often
153
+ * than `null`, and `<Image source={{uri: ""}}>` is a request that fails
154
+ * silently on web and renders an empty square on native.
155
+ */
156
+ export function customIcon(
157
+ iconUrl: string | null | undefined,
158
+ failed: boolean
159
+ ): { kind: "image"; uri: string } | { kind: "fallback" } {
160
+ const uri = iconUrl?.trim();
161
+ if (!uri || failed) {
162
+ return { kind: "fallback" };
163
+ }
164
+ return { kind: "image", uri };
165
+ }
166
+
102
167
  /**
103
168
  * Button row for federated sign-in: Entropy / Apple / Google / Microsoft.
104
169
  *
@@ -128,6 +193,7 @@ export function SocialConnections({
128
193
  showApple = true,
129
194
  showGoogle = true,
130
195
  showMicrosoft = true,
196
+ custom = [],
131
197
  }: SocialConnectionsProps): React.JSX.Element {
132
198
  const { colorScheme } = useColorScheme();
133
199
  const isDark = colorScheme === "dark";
@@ -178,8 +244,68 @@ export function SocialConnections({
178
244
  </Tooltip>
179
245
  )
180
246
  )}
247
+ {custom.map((provider) => (
248
+ <CustomProviderButton
249
+ // Namespaced so a caller's key cannot collide with a built-in's and
250
+ // silently replace it in the reconciler.
251
+ key={`custom:${provider.key}`}
252
+ provider={provider}
253
+ isDark={isDark}
254
+ />
255
+ ))}
181
256
  </View>
182
257
  );
183
258
  }
184
259
 
260
+ /**
261
+ * One caller-supplied provider.
262
+ *
263
+ * Its own component because it holds state the built-ins do not: whether the
264
+ * remote icon failed. A broken URL has to degrade to the neutral glyph, and
265
+ * `onError` can only be observed per image.
266
+ */
267
+ function CustomProviderButton({
268
+ provider,
269
+ isDark,
270
+ }: {
271
+ provider: CustomProvider;
272
+ isDark: boolean;
273
+ }): React.JSX.Element {
274
+ const [iconFailed, setIconFailed] = React.useState(false);
275
+ const tint = isDark ? "#FFFFFF" : "#000000";
276
+ const icon = customIcon(provider.iconUrl, iconFailed);
277
+
278
+ return (
279
+ <Tooltip delayDuration={200}>
280
+ <TooltipTrigger asChild>
281
+ <Pressable
282
+ onPress={provider.onPress}
283
+ className="h-12 w-12 items-center justify-center rounded-lg border border-border dark:border-neutral-600 active:opacity-70"
284
+ accessibilityRole="button"
285
+ accessibilityLabel={`Continue with ${provider.label}`}
286
+ >
287
+ {icon.kind === "image" ? (
288
+ <Image
289
+ source={{ uri: icon.uri }}
290
+ style={{ width: 22, height: 22 }}
291
+ // `contain` rather than `cover`: an operator's mark is whatever
292
+ // aspect ratio they have, and cropping somebody's logo to a
293
+ // square is worse than letterboxing it.
294
+ resizeMode="contain"
295
+ onError={() => setIconFailed(true)}
296
+ accessibilityIgnoresInvertColors
297
+ />
298
+ ) : (
299
+ // The neutral fallback. A key rather than a globe or a puzzle
300
+ // piece: this is a sign-in credential, and the glyph should say so
301
+ // without implying a vendor.
302
+ <Ionicons name="key-outline" size={22} color={tint} />
303
+ )}
304
+ </Pressable>
305
+ </TooltipTrigger>
306
+ <TooltipContent>{`Continue with ${provider.label}`}</TooltipContent>
307
+ </Tooltip>
308
+ );
309
+ }
310
+
185
311
  export default SocialConnections;