@vuu-ui/vuu-utils 4.0.0-alpha.3 → 4.0.0-alpha.30

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.
Files changed (51) hide show
  1. package/package.json +9 -8
  2. package/src/array-utils.js +5 -4
  3. package/src/column-utils.js +28 -10
  4. package/src/component-registry.js +2 -1
  5. package/src/data-utils.js +1 -0
  6. package/src/datasource/BaseDataSource.js +5 -3
  7. package/src/date/EpochTimestamp.js +85 -0
  8. package/src/date/date-utils.js +50 -18
  9. package/src/date/dateTimePattern.js +33 -5
  10. package/src/date/formatter.js +54 -16
  11. package/src/date/index.js +5 -2
  12. package/src/date/temporal.js +131 -0
  13. package/src/date/time-zone.js +56 -0
  14. package/src/feature-utils.js +7 -1
  15. package/src/filters/filter-utils.js +13 -7
  16. package/src/filters/filterAsQuery.js +107 -45
  17. package/src/filters/index.js +1 -0
  18. package/src/filters/temporal-cell-filter.js +63 -0
  19. package/src/form-utils.js +44 -6
  20. package/src/formatting-utils.js +48 -26
  21. package/src/html-utils.js +42 -1
  22. package/src/keyset.js +15 -9
  23. package/src/round-decimal.js +10 -2
  24. package/src/useResizeObserver.js +3 -3
  25. package/src/vendor/@preact/signals-core/dist/signals-core.js +1 -1
  26. package/src/vendor/@preact/signals-core/dist/signals-core.js.map +1 -1
  27. package/types/ThemeProvider.d.ts +1 -1
  28. package/types/array-utils.d.ts +3 -2
  29. package/types/column-utils.d.ts +43 -40
  30. package/types/component-registry.d.ts +4 -4
  31. package/types/context-definitions/DataProvider.d.ts +1 -1
  32. package/types/context-definitions/DataSourceProvider.d.ts +1 -1
  33. package/types/datasource/BaseDataSource.d.ts +2 -2
  34. package/types/date/EpochTimestamp.d.ts +66 -0
  35. package/types/date/date-utils.d.ts +34 -9
  36. package/types/date/dateTimePattern.d.ts +20 -2
  37. package/types/date/formatter.d.ts +26 -1
  38. package/types/date/index.d.ts +6 -2
  39. package/types/date/temporal.d.ts +68 -0
  40. package/types/date/time-zone.d.ts +52 -0
  41. package/types/feature-utils.d.ts +15 -1
  42. package/types/filters/filter-utils.d.ts +6 -1
  43. package/types/filters/filterAsQuery.d.ts +41 -0
  44. package/types/filters/index.d.ts +1 -0
  45. package/types/filters/scaled-decimal-filter.d.ts +58 -0
  46. package/types/filters/temporal-cell-filter.d.ts +27 -0
  47. package/types/form-utils.d.ts +19 -0
  48. package/types/formatting-utils.d.ts +23 -1
  49. package/types/html-utils.d.ts +21 -0
  50. package/types/keyset.d.ts +11 -1
  51. package/types/tree-types.d.ts +2 -0
@@ -0,0 +1,58 @@
1
+ import type { ExtendedFilterOptions, ScaledDecimalFilterOptions, SingleValueFilterClause } from "@vuu-ui/vuu-filter-types";
2
+ import type { DataValueDescriptor } from "@vuu-ui/vuu-data-types";
3
+ export type ScaledDecimalScale = ScaledDecimalFilterOptions["scale"];
4
+ export declare const getScaledDecimalScale: (serverDataType?: string) => ScaledDecimalScale | undefined;
5
+ export declare const isValidDecimalString: (value: string) => boolean;
6
+ export declare const isScaledDecimalFilterOptions: (options?: ExtendedFilterOptions) => options is ScaledDecimalFilterOptions;
7
+ /**
8
+ * A decimal (not exponential) string representation of a filter value.
9
+ */
10
+ export declare const toDecimalString: (value: unknown, scale: ScaledDecimalScale) => string;
11
+ /**
12
+ * Convert a decimal string to its scaled integer representation. Digits beyond
13
+ * the scale are truncated, as the Vuu server does.
14
+ */
15
+ export declare const toScaledInteger: (value: string, scale: ScaledDecimalScale) => bigint;
16
+ /**
17
+ * Convert a scaled integer to a decimal string with 'scale' decimal places,
18
+ * the literal form in which scaled decimals are expressed in a filter query.
19
+ */
20
+ export declare const fromScaledInteger: (value: bigint, scale: ScaledDecimalScale) => string;
21
+ /**
22
+ * The filter options for a clause on a scaled decimal column, describing the
23
+ * precision with which the column displays values. These mirror the formatting
24
+ * rules of numericFormatter: a column with no type descriptor displays the full
25
+ * value, a type descriptor with no decimals displays 4 decimal places.
26
+ */
27
+ export declare const getScaledDecimalFilterOptions: (column: Pick<DataValueDescriptor, "serverDataType" | "type">) => ScaledDecimalFilterOptions | undefined;
28
+ /**
29
+ * The range of scaled integer values, inclusive at both ends, matched by a
30
+ * filter value. A value with no more decimal places than are displayed matches
31
+ * every value that displays as that value, e.g 1.23, displayed with 2 decimals,
32
+ * rounded, matches [1.225, 1.235). Display rounding applies to the magnitude,
33
+ * so -1.23 matches (-1.235, -1.225]. A value with more decimal places than are
34
+ * displayed is matched at its own precision, by the same rounding rule, e.g
35
+ * 1.234 matches [1.2335, 1.2345). A value with as many decimal places as the
36
+ * column holds, or any value where every decimal is displayed, is matched exactly.
37
+ */
38
+ export declare const getScaledDecimalMatchRange: (value: string, { scale, decimals, roundingRule }: ScaledDecimalFilterOptions) => [bigint, bigint];
39
+ /**
40
+ * Serialize a filter clause on a scaled decimal column. Where the value matches
41
+ * a range of values (see getScaledDecimalMatchRange), each operator applies to
42
+ * that range, e.g '>' matches values greater than every value in the range.
43
+ * Note: '!=' on a range is expressed as '< from or > to', which, unlike an
44
+ * exact '!=', does not match a null value.
45
+ */
46
+ export declare const scaledDecimalFilterAsQuery: ({ column, op, value, }: Pick<SingleValueFilterClause, "column" | "op" | "value">, options: ScaledDecimalFilterOptions) => string;
47
+ export interface ScaledDecimalCellFilter {
48
+ /** The value as displayed */
49
+ label: string;
50
+ op: "=";
51
+ value: string;
52
+ }
53
+ /**
54
+ * The filter for a cell value on a scaled decimal column, matching the value as
55
+ * displayed, e.g a cell displaying 1.23 (underlying value 1.234567) creates a
56
+ * filter matching every value that displays as 1.23.
57
+ */
58
+ export declare const getScaledDecimalCellFilter: (column: Pick<DataValueDescriptor, "serverDataType" | "type">, value: unknown) => ScaledDecimalCellFilter | undefined;
@@ -0,0 +1,27 @@
1
+ import type { DataValueDescriptor } from "@vuu-ui/vuu-data-types";
2
+ export interface TemporalCellFilter {
3
+ /** The value, formatted as displayed */
4
+ label: string;
5
+ op: "=" | "between-inclusive";
6
+ value: string | [string, string];
7
+ }
8
+ /**
9
+ * Describes a filter that matches a temporal value at the precision with which
10
+ * it is displayed by the given column descriptor, e.g. where the descriptor
11
+ * displays milliseconds, the filter matches the whole millisecond.
12
+ * - date => the whole day, as a start of day value
13
+ * - time => a time of day (TimeString), truncated to the displayed precision
14
+ * - datetime => a range, unless the displayed precision is that of the encoding
15
+ * The filter is suitable for FilterAggregator.add (with the same descriptor) and
16
+ * matches the value a ColumnFilter with this descriptor would commit.
17
+ *
18
+ * @param column the descriptor of the filter (or table cell) displaying the value
19
+ * @param value a value as received from the server
20
+ * @param columnFilter the value is displayed by a ColumnFilter, rather than a
21
+ * table cell. A ColumnFilter displays a 'datetime' value as a date (DatePicker,
22
+ * so the filter is the whole day) and a 'time' value to the second, or to the
23
+ * millisecond with the 'hh:mm:ss.ms' pattern (TimeInput supports no finer
24
+ * precision, whereas a table cell displays nanos by default).
25
+ * @returns undefined if value is empty or column is not temporal
26
+ */
27
+ export declare const getTemporalCellFilter: (column: DataValueDescriptor, value: unknown, columnFilter?: boolean) => TemporalCellFilter | undefined;
@@ -1,7 +1,11 @@
1
1
  import { DataValueTypeSimple } from "@vuu-ui/vuu-data-types";
2
2
  import { VuuColumnDataType, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
3
3
  import { KeyboardEvent, SyntheticEvent } from "react";
4
+ import { EpochTimestamp } from "./date/EpochTimestamp";
5
+ import { type TemporalInfo } from "./date/temporal";
6
+ import type { DataValueDescriptor } from "@vuu-ui/vuu-data-types";
4
7
  import { ExtendedFilterOptions } from "@vuu-ui/vuu-filter-types";
8
+ import { type ScaledDecimal } from "./ScaledDecimal";
5
9
  export declare class DataValidationError extends Error {
6
10
  actualType: string;
7
11
  expectedType: string;
@@ -35,3 +39,18 @@ export declare function getTypedRange([value1, value2]: [string, string], dataTy
35
39
  */
36
40
  export declare function getTypedValue(value: string, type: VuuColumnDataType | DataValueTypeSimple, throwIfInvalid?: false, options?: ExtendedFilterOptions): VuuRowDataItemType | undefined;
37
41
  export declare function getTypedValue(value: string, type: VuuColumnDataType | DataValueTypeSimple, throwIfInvalid: true, options?: ExtendedFilterOptions): VuuRowDataItemType;
42
+ /**
43
+ * Convert a string value (from user input or a filter control) to the wire
44
+ * representation of a temporal value, using the column's TemporalInfo.
45
+ * - time kind: a TimeString is applied to today's date (in the column time zone)
46
+ * - any kind: canonical input (see parseTemporalInput) or raw epoch digits
47
+ * Values are returned in the column encoding (number for epochMillis, string
48
+ * for epochNanos).
49
+ */
50
+ export declare function getTypedTemporalValue(value: string, temporalInfo: TemporalInfo, throwIfInvalid?: boolean, baseValue?: EpochTimestamp): number | string | undefined;
51
+ /**
52
+ * Like getTypedValue, but takes a column (or form field) descriptor. Temporal
53
+ * values are handled according to getTemporalInfo, other values according to
54
+ * the type name, if there is one, otherwise the serverDataType.
55
+ */
56
+ export declare function getTypedValueForDescriptor(value: string, descriptor: DataValueDescriptor, throwIfInvalid?: boolean): VuuRowDataItemType | ScaledDecimal | bigint | undefined;
@@ -1,8 +1,30 @@
1
- import { ColumnDescriptor, ValueFormatter } from "@vuu-ui/vuu-table-types";
1
+ import { DataValueDescriptor } from "@vuu-ui/vuu-data-types";
2
+ import { ColumnDescriptor, FractionalSecondDigits, ValueFormatter } from "@vuu-ui/vuu-table-types";
2
3
  export type ValueFormatters = {
3
4
  [key: string]: ValueFormatter;
4
5
  };
5
6
  export declare const defaultValueFormatter: (value: unknown) => string;
7
+ /**
8
+ * The number of fractional second digits displayed for a temporal value:
9
+ * type.formatting.fractionalSecondDigits if set, otherwise 3 for an
10
+ * 'hh:mm:ss.ms' time pattern, 9 for a nanosecond column with any other time
11
+ * pattern, else 0.
12
+ */
13
+ export declare const getFractionalSecondDigits: (column: DataValueDescriptor, temporalInfo?: import("./date").TemporalInfo | undefined) => FractionalSecondDigits;
14
+ /**
15
+ * Creates a formatter for a temporal value (see getTemporalInfo). Handles
16
+ * millisecond and nanosecond encodings, the configured (or default) pattern,
17
+ * time zone, locale and fractional second digits.
18
+ * Empty values (null, undefined, '', 0) are rendered as empty string.
19
+ */
20
+ export declare const temporalFormatter: (column: DataValueDescriptor, temporalInfo?: import("./date").TemporalInfo | undefined) => ValueFormatter;
21
+ /**
22
+ * Format a filter value on a temporal column for display (e.g. in a FilterPill
23
+ * tooltip or a list of filter clauses). Time of day (TimeString) values are
24
+ * displayed as is. A 'datetime' value at the start of a day (which the filter
25
+ * applies to the whole day, see temporalFilterAsQuery) is displayed as a date.
26
+ */
27
+ export declare const formatTemporalFilterValue: (value: unknown, column: DataValueDescriptor) => string;
6
28
  export declare const numericFormatter: ({ align, serverDataType, type, }: Partial<ColumnDescriptor>) => typeof defaultValueFormatter;
7
29
  export declare const getValueFormatter: (column: ColumnDescriptor) => ValueFormatter;
8
30
  /**
@@ -12,7 +12,28 @@ export declare const isSelectableElement: (el?: HTMLElement | null) => boolean;
12
12
  export declare const isInputElement: (el: HTMLElement | EventTarget | null) => el is HTMLInputElement;
13
13
  export declare const isDateInput: (el: HTMLElement | EventTarget | null) => el is HTMLInputElement;
14
14
  export declare const hasOpenOptionList: (el: HTMLElement | EventTarget | null) => boolean | undefined;
15
+ /**
16
+ * Test whether viewport coordinates (e.g. clientX, clientY from a pointer
17
+ * event) fall within the bounding rect of an element.
18
+ */
19
+ export declare const containsPoint: (el: HTMLElement | null, x: number, y: number) => boolean;
15
20
  export declare function getScrollbarSize(): number;
21
+ /**
22
+ * Used when the max scroll height cannot be measured, e.g. outside a browser.
23
+ */
24
+ export declare const DEFAULT_MAX_SCROLL_HEIGHT = 33000000;
25
+ /**
26
+ * Measure the largest scrollHeight (in CSS pixels) the browser supports for a
27
+ * scrollable element. Engines have an internal layout limit, which shrinks in
28
+ * CSS pixels as browser zoom increases, e.g.
29
+ * Chromium/WebKit: ~33.5M at 100%, ~11.18M at 300%
30
+ * Firefox: ~17.9M at 100%, ~5.97M at 300%
31
+ * Chromium/WebKit clamp heights above the limit, Firefox ignores them entirely,
32
+ * so a single oversized probe cannot be used. Instead we binary search for the
33
+ * largest height that is honoured. Browser zoom changes devicePixelRatio, so
34
+ * results are cached per ratio.
35
+ */
36
+ export declare function getMaxScrollHeight(doc?: Document | undefined): number;
16
37
  export type MouseEventTypes = "dblclick" | "click";
17
38
  export type KeyboardEventTypes = "keydown" | "keypress" | "keyup";
18
39
  export declare const dispatchMouseEvent: (el: HTMLElement, type: MouseEventTypes) => void;
package/types/keyset.d.ts CHANGED
@@ -5,12 +5,22 @@ export interface IKeySet {
5
5
  }
6
6
  export declare class KeySet implements IKeySet {
7
7
  private keys;
8
+ private freeKeys;
8
9
  private nextKeyValue;
9
10
  private range;
10
11
  constructor(range: VuuRange);
11
12
  next(free?: number[]): number;
12
13
  private init;
13
- reset(range: VuuRange): boolean;
14
+ /**
15
+ * Keys assigned to rows that remain within range are never changed, keys
16
+ * released by rows leaving the range are recycled for rows entering the
17
+ * range. Keys are never re-sequenced, clients may retain rows (and their
18
+ * keys) that remain within range, so re-assigning keys to those rows would
19
+ * risk duplicate keys on the client.
20
+ * Note: range is copied, callers may mutate the range object they pass.
21
+ * Returns false, keys are never resequenced.
22
+ */
23
+ reset({ from, to }: VuuRange): boolean;
14
24
  keyFor(rowIndex: number): number;
15
25
  toDebugString(): string;
16
26
  }
@@ -5,5 +5,7 @@ export interface TreeSourceNode<T = unknown> {
5
5
  header?: boolean;
6
6
  label: string;
7
7
  childNodes?: TreeSourceNode<T>[];
8
+ /** node is rendered expanded initially */
9
+ expanded?: boolean;
8
10
  tags?: string[];
9
11
  }