tosijs-ui 1.16.11 → 1.16.12

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,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.16.12
4
+
5
+ Two additions for task-focused screens: a table row can open to show a detail element, and a
6
+ schema form can show a hand-picked set of fields. Both are off until you ask for them.
7
+
8
+ - **`<tosi-table>` rows can expand to a detail element** (#220). Set
9
+ `rowDetail = (row) => element` and each row can open to show that element underneath it,
10
+ across the full width of the table. A column with `expander: true` renders the toggle;
11
+ `toggleRowDetail(row, open?)` does it from code, and `rowexpand` / `rowcollapse` report it.
12
+ The detail stays in view while the columns scroll sideways, is built once per expansion and
13
+ kept while the row is scrolled out of view, and the toggled row keeps its place on screen.
14
+ Expansion follows the row through sorting and filtering; with `rowId` it also survives a
15
+ reload of the data, and `expandedRowIds` can be read and set. `rowHasDetail` hides the
16
+ toggle on rows with nothing to show. Pinned rows are not expandable. A table placed in a
17
+ detail keeps its own selection, editing and column resizing.
18
+ - **The scrollbar of a table with `rowDetail` is approximate.** Rows are no longer all one
19
+ height, so the table places them by interpolation (tosijs's variable-height list). A table
20
+ that does not set `rowDetail` is unchanged.
21
+ - **`<tosi-schema-form>` takes a `fields` map for curated forms** (#221). It maps paths into
22
+ the schema to `{ caption, help, readOnly, editor }`, in display order, and the form shows
23
+ only those. Controls, choices, `required` and constraints still come from the schema.
24
+ `editor` is any function returning an element with a `value` and a `change` event, such as
25
+ an element creator from this library, or a field plugin object. The editor's `value` must be
26
+ of the schema's type, so a native `<input>` suits string properties only.
27
+ - **A curated form still owns the whole value.** Properties that are not shown keep their
28
+ values, the whole value is validated, and an error in a property that is not shown is
29
+ listed above the fields. A path the schema does not describe renders as a placeholder that
30
+ says so.
31
+ - **Fixed: an error on a plugin-rendered field was never shown** under that field. The form
32
+ now shows it there, a missing required value included, as it does for built-in controls.
33
+ - **Fixed: `readOnly` on a schema form did not reach a plugin control that is a custom
34
+ element, or a `<textarea>`.** Both are now locked with the rest of the form, through
35
+ `disabled` or, for a component that has only that, `readOnly`. Of these, the form
36
+ releases only what it locked: one a plugin disabled itself stays disabled.
37
+
38
+ `dist/iife.js` grows by about 2.5 kB gzip.
39
+
3
40
  ## 1.16.11
4
41
 
5
42
  In-page links work, teaching examples show their test result, and "Download ePub" stops
@@ -38,9 +38,17 @@ export interface ColumnOptions {
38
38
  * table has no business reaching into it.
39
39
  */
40
40
  editable?: boolean;
41
+ /**
42
+ * Render this column as the row's disclosure toggle for `rowDetail`. The cell holds one
43
+ * button; `prop` is unused (give it any unique string) and the header is left blank
44
+ * unless you set `name`.
45
+ */
46
+ expander?: boolean;
41
47
  headerCell?: (options: ColumnOptions) => HTMLElement;
42
48
  dataCell?: (options: ColumnOptions) => HTMLElement;
43
49
  }
50
+ /** Builds the element shown under an expanded row. `null` means the row has no detail. */
51
+ export type RowDetailFn = (row: any) => HTMLElement | null;
44
52
  export interface TableData {
45
53
  columns?: ColumnOptions[] | null;
46
54
  array: any[];
@@ -164,6 +172,46 @@ export declare class TosiTable extends TosiTable_base {
164
172
  ':host .row-edge-top': {
165
173
  boxShadow: string;
166
174
  };
175
+ ':host .scroll-area.has-row-detail': {
176
+ containerType: string;
177
+ };
178
+ ':host .tr.row-expanded': {
179
+ height: string;
180
+ };
181
+ ':host .tr-detail': {
182
+ gridColumn: string;
183
+ position: string;
184
+ left: string;
185
+ width: string;
186
+ boxSizing: string;
187
+ padding: string;
188
+ background: string;
189
+ boxShadow: string;
190
+ };
191
+ ':host .td.expander-cell': {
192
+ justifyContent: string;
193
+ padding: number;
194
+ };
195
+ ':host .row-expander': {
196
+ color: string;
197
+ background: string;
198
+ boxShadow: string;
199
+ padding: number;
200
+ display: string;
201
+ alignItems: string;
202
+ justifyContent: string;
203
+ width: string;
204
+ height: string;
205
+ };
206
+ ':host .row-expander[hidden]': {
207
+ display: string;
208
+ };
209
+ ':host .row-expander > *': {
210
+ transition: string;
211
+ };
212
+ ':host .row-expander[aria-expanded="true"] > *': {
213
+ transform: string;
214
+ };
167
215
  ':host .th .menu-trigger': {
168
216
  color: string;
169
217
  background: string;
@@ -195,6 +243,63 @@ export declare class TosiTable extends TosiTable_base {
195
243
  get schema(): JSONSchema | null;
196
244
  set schema(schema: JSONSchema | null);
197
245
  selectionChanged: SelectCallback;
246
+ private _rowDetail;
247
+ private _rowId;
248
+ /** Keys of the expanded rows: `rowId(row)` when there is a `rowId`, else the row itself. */
249
+ private _expanded;
250
+ /** One detail container per expanded row, kept so its state survives scrolling. */
251
+ private _detailEls;
252
+ /** The row each detail was built from: a detail is only as current as its row. */
253
+ private _detailRows;
254
+ private _detailCount;
255
+ /**
256
+ * Builds the element shown under an expanded row, from that row's data. Return `null`
257
+ * for a row with no detail. Called once per expansion: the element is kept while the row
258
+ * stays expanded (scrolling it out of view and back does not rebuild it) and dropped when
259
+ * the row collapses or the table's `array` is replaced.
260
+ */
261
+ get rowDetail(): RowDetailFn | null;
262
+ set rowDetail(fn: RowDetailFn | null);
263
+ /**
264
+ * Which rows have a detail, for the `expander` column: a row this returns `false` for
265
+ * gets no toggle. Unset, every row gets one.
266
+ */
267
+ rowHasDetail: ((row: any) => boolean) | null;
268
+ /**
269
+ * A stable id for a row. Without it expansion follows the row OBJECT, which is enough
270
+ * for sorting and filtering; with it expansion also survives replacing `array` with new
271
+ * objects, and `expandedRowIds` can be read and set.
272
+ */
273
+ get rowId(): ((row: any) => string) | null;
274
+ set rowId(fn: ((row: any) => string) | null);
275
+ private _pendingExpandedIds;
276
+ private _warnedPendingIds;
277
+ /**
278
+ * Ids of the expanded rows. Needs `rowId`; without one this reads empty. Assigning it
279
+ * fires no `rowexpand` / `rowcollapse`: those report a toggle, not a restore.
280
+ */
281
+ get expandedRowIds(): string[];
282
+ set expandedRowIds(ids: string[] | null);
283
+ private forgetDetails;
284
+ private detailKey;
285
+ isRowExpanded(row: any): boolean;
286
+ /**
287
+ * Expand or collapse a row's detail (`open` omitted toggles). Fires `rowexpand` or
288
+ * `rowcollapse` with `detail: { row, element }`. The toggled row keeps its place on
289
+ * screen.
290
+ */
291
+ toggleRowDetail(row: any, open?: boolean): void;
292
+ /** The detail container for a row, built on first use. `null` when the row has none. */
293
+ private detailFor;
294
+ private stampedRow;
295
+ /** A row's cells: its children, less the detail that an expanded row also holds. */
296
+ private rowCells;
297
+ private syncDetail;
298
+ private syncStampedDetails;
299
+ /** Have the virtual list re-measure its rows after one changed height. */
300
+ private remeasureRows;
301
+ /** Is this event target inside one of THIS table's row details? */
302
+ private inDetail;
198
303
  rowRendered: ((item: any, cells: HTMLElement[]) => void) | null;
199
304
  private selectedKey;
200
305
  private selectBinding;