@orianatech/pire 0.15.0 → 0.17.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.
@@ -7,12 +7,28 @@ export interface DataTableColumn<T = any> {
7
7
  /** Right-aligns and switches to tabular mono. Use for every amount, quantity and ID. */
8
8
  numeric?: boolean;
9
9
  sortable?: boolean;
10
+ /**
11
+ * Keeps `label` for assistive tech but not on screen. For a utility column — a disclosure or
12
+ * row-action column — where a visible header is noise. An *empty* label is not the answer: a
13
+ * header with no text leaves its column unnamed for anyone using a screen reader.
14
+ */
15
+ hideLabel?: boolean;
10
16
  render?: (row: T) => React.ReactNode;
11
17
  }
12
18
  export interface DataTableSort {
13
19
  key: string;
14
20
  dir: 'asc' | 'desc';
15
21
  }
22
+ export interface DataTableRowProps {
23
+ /** Extra class on the `<tr>`. */
24
+ className?: string;
25
+ /**
26
+ * Greys the row and takes it out of selection and row actions. Use it when a row is present for
27
+ * context but cannot be acted on — and pair it with a cell that says *why*, since a greyed row
28
+ * on its own does not explain itself.
29
+ */
30
+ isDisabled?: boolean;
31
+ }
16
32
  export interface DataTableProps<T extends {
17
33
  id: string | number;
18
34
  } = any> {
@@ -29,6 +45,25 @@ export interface DataTableProps<T extends {
29
45
  onSortChange?: (sort: DataTableSort) => void;
30
46
  onRowAction?: (row: T) => void;
31
47
  emptyLabel?: React.ReactNode;
48
+ /**
49
+ * Summary cells keyed by column, rendered in a real `<tfoot>`.
50
+ *
51
+ * Keyed rather than free-form so a total sits under the column it totals, and stays there when
52
+ * columns are reordered or resized. Columns missing from the map get an empty cell. Hidden while
53
+ * `isLoading`, since a total from the previous response next to skeleton rows reads as current.
54
+ */
55
+ footer?: Record<string, React.ReactNode>;
56
+ /** Per-row presentation and interactivity. Called for every row on every render — keep it cheap. */
57
+ rowProps?: (row: T) => DataTableRowProps;
58
+ /**
59
+ * Detail rendered in a full-width row beneath its parent, for the rows named by `expandedIds`.
60
+ *
61
+ * Expansion is controlled: put the trigger in a column's `render` and track the ids yourself.
62
+ * The table has no opinion on what opens a row, because the affordance differs per screen.
63
+ */
64
+ renderExpanded?: (row: T) => React.ReactNode;
65
+ /** Ids whose `renderExpanded` content is currently shown. */
66
+ expandedIds?: Array<string | number>;
32
67
  /** Swaps the body for skeleton rows derived from `columns` and `density`, keeping the header. */
33
68
  isLoading?: boolean;
34
69
  /** Skeleton row count. Defaults to the current `rows` length, or 5 when there are none. */
@@ -43,4 +78,4 @@ export interface DataTableProps<T extends {
43
78
  * screen-reader row/column announcements — do not hand-roll a <table> in product code. */
44
79
  export declare function DataTable<T extends {
45
80
  id: string | number;
46
- }>({ columns, rows, density, selectable, selected, onSelectionChange, sort, onSortChange, onRowAction, stickyHeader, emptyLabel, isLoading, loadingRowCount, loadingLabel, className, style, ...rest }: DataTableProps<T>): React.JSX.Element;
81
+ }>({ columns, rows, density, selectable, selected, onSelectionChange, sort, onSortChange, onRowAction, stickyHeader, emptyLabel, isLoading, loadingRowCount, loadingLabel, footer, rowProps, renderExpanded, expandedIds, className, style, ...rest }: DataTableProps<T>): React.JSX.Element;
@@ -7,12 +7,28 @@ export interface DataTableColumn<T = any> {
7
7
  /** Right-aligns and switches to tabular mono. Use for every amount, quantity and ID. */
8
8
  numeric?: boolean;
9
9
  sortable?: boolean;
10
+ /**
11
+ * Keeps `label` for assistive tech but not on screen. For a utility column — a disclosure or
12
+ * row-action column — where a visible header is noise. An *empty* label is not the answer: a
13
+ * header with no text leaves its column unnamed for anyone using a screen reader.
14
+ */
15
+ hideLabel?: boolean;
10
16
  render?: (row: T) => React.ReactNode;
11
17
  }
12
18
  export interface DataTableSort {
13
19
  key: string;
14
20
  dir: 'asc' | 'desc';
15
21
  }
22
+ export interface DataTableRowProps {
23
+ /** Extra class on the `<tr>`. */
24
+ className?: string;
25
+ /**
26
+ * Greys the row and takes it out of selection and row actions. Use it when a row is present for
27
+ * context but cannot be acted on — and pair it with a cell that says *why*, since a greyed row
28
+ * on its own does not explain itself.
29
+ */
30
+ isDisabled?: boolean;
31
+ }
16
32
  export interface DataTableProps<T extends {
17
33
  id: string | number;
18
34
  } = any> {
@@ -29,6 +45,25 @@ export interface DataTableProps<T extends {
29
45
  onSortChange?: (sort: DataTableSort) => void;
30
46
  onRowAction?: (row: T) => void;
31
47
  emptyLabel?: React.ReactNode;
48
+ /**
49
+ * Summary cells keyed by column, rendered in a real `<tfoot>`.
50
+ *
51
+ * Keyed rather than free-form so a total sits under the column it totals, and stays there when
52
+ * columns are reordered or resized. Columns missing from the map get an empty cell. Hidden while
53
+ * `isLoading`, since a total from the previous response next to skeleton rows reads as current.
54
+ */
55
+ footer?: Record<string, React.ReactNode>;
56
+ /** Per-row presentation and interactivity. Called for every row on every render — keep it cheap. */
57
+ rowProps?: (row: T) => DataTableRowProps;
58
+ /**
59
+ * Detail rendered in a full-width row beneath its parent, for the rows named by `expandedIds`.
60
+ *
61
+ * Expansion is controlled: put the trigger in a column's `render` and track the ids yourself.
62
+ * The table has no opinion on what opens a row, because the affordance differs per screen.
63
+ */
64
+ renderExpanded?: (row: T) => React.ReactNode;
65
+ /** Ids whose `renderExpanded` content is currently shown. */
66
+ expandedIds?: Array<string | number>;
32
67
  /** Swaps the body for skeleton rows derived from `columns` and `density`, keeping the header. */
33
68
  isLoading?: boolean;
34
69
  /** Skeleton row count. Defaults to the current `rows` length, or 5 when there are none. */
@@ -43,5 +78,5 @@ export interface DataTableProps<T extends {
43
78
  * screen-reader row/column announcements — do not hand-roll a <table> in product code. */
44
79
  export declare function DataTable<T extends {
45
80
  id: string | number;
46
- }>({ columns, rows, density, selectable, selected, onSelectionChange, sort, onSortChange, onRowAction, stickyHeader, emptyLabel, isLoading, loadingRowCount, loadingLabel, className, style, ...rest }: DataTableProps<T>): React.JSX.Element;
81
+ }>({ columns, rows, density, selectable, selected, onSelectionChange, sort, onSortChange, onRowAction, stickyHeader, emptyLabel, isLoading, loadingRowCount, loadingLabel, footer, rowProps, renderExpanded, expandedIds, className, style, ...rest }: DataTableProps<T>): React.JSX.Element;
47
82
  //# sourceMappingURL=DataTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AASpC,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE;AAEnE,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,GAAG;IACrE,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,oEAAoE;IACpE,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IAC1D,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,iGAAiG;IACjG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2FAA2F;IAC3F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;2FAC2F;AAC3F,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAmB,EAC/F,UAAU,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,YAAmB,EAC7F,UAAoD,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAC9F,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,qBAkF/C"}
1
+ {"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,17 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
+ export interface DialogSlotProps {
3
+ children?: React.ReactNode;
4
+ className?: string;
5
+ }
6
+ /** The dialog's heading. Wires itself to the dialog's accessible name through React Aria's
7
+ * `slot="title"`, which is why it cannot be replaced by a bare heading element. */
8
+ export declare function DialogTitle({ children, className }: DialogSlotProps): React.JSX.Element;
9
+ /** One line under the title. Say what the action affects, not what the button is called. */
10
+ export declare function DialogDescription({ children, className }: DialogSlotProps): React.JSX.Element;
11
+ /** The scrollable middle. Omit it entirely when the title and description say everything. */
12
+ export declare function DialogBody({ children, className }: DialogSlotProps): React.JSX.Element;
13
+ /** The action row. Cancel first, the commit or destructive action last. */
14
+ export declare function DialogActions({ children, className }: DialogSlotProps): React.JSX.Element;
2
15
  export interface DialogProps {
3
16
  isOpen?: boolean;
4
17
  onOpenChange?: (open: boolean) => void;
@@ -1,4 +1,17 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
+ export interface DialogSlotProps {
3
+ children?: React.ReactNode;
4
+ className?: string;
5
+ }
6
+ /** The dialog's heading. Wires itself to the dialog's accessible name through React Aria's
7
+ * `slot="title"`, which is why it cannot be replaced by a bare heading element. */
8
+ export declare function DialogTitle({ children, className }: DialogSlotProps): React.JSX.Element;
9
+ /** One line under the title. Say what the action affects, not what the button is called. */
10
+ export declare function DialogDescription({ children, className }: DialogSlotProps): React.JSX.Element;
11
+ /** The scrollable middle. Omit it entirely when the title and description say everything. */
12
+ export declare function DialogBody({ children, className }: DialogSlotProps): React.JSX.Element;
13
+ /** The action row. Cancel first, the commit or destructive action last. */
14
+ export declare function DialogActions({ children, className }: DialogSlotProps): React.JSX.Element;
2
15
  export interface DialogProps {
3
16
  isOpen?: boolean;
4
17
  onOpenChange?: (open: boolean) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAMpC,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,mEAAmE;IACnE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oEAAoE;IACpE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,yFAAyF;IACzF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;0DAC0D;AAC1D,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EACvF,IAAW,EAAE,aAAoB,EAAE,SAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,qBA2BrF"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;oFACoF;AACpF,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,qBAEnE;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,qBAEzE;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,qBAElE;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,qBAErE;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,mEAAmE;IACnE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oEAAoE;IACpE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,yFAAyF;IACzF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;0DAC0D;AAC1D,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EACvF,IAAW,EAAE,aAAoB,EAAE,SAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,qBAwDrF"}
@@ -1,11 +1,23 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
2
  export interface TooltipProps {
3
3
  /** Short clarifying text — never the only source of an instruction. */
4
4
  label: React.ReactNode;
5
5
  placement?: 'top' | 'bottom' | 'left' | 'right';
6
6
  /** Hover delay in ms. Keyboard focus always shows it immediately. */
7
7
  delay?: number;
8
- /** A single focusable element (Button, IconButton, Link). */
8
+ /**
9
+ * Anything — a Button, a Badge, a span, plain text.
10
+ *
11
+ * A child that cannot take focus on its own is made focusable for you. That is the point: a
12
+ * tooltip on something unreachable by keyboard is invisible to anyone not using a mouse, and it
13
+ * fails silently — a dead tooltip is indistinguishable from a live one until somebody hovers it.
14
+ */
9
15
  children: React.ReactNode;
10
16
  }
17
+ /**
18
+ * Explains something without adding a step. Shows on hover after `delay`, and immediately on
19
+ * keyboard focus.
20
+ *
21
+ * Never put an instruction here that is not available elsewhere: there is no hover on touch.
22
+ */
11
23
  export declare function Tooltip({ label, placement, delay, children }: TooltipProps): React.JSX.Element;
@@ -1,12 +1,24 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
2
  export interface TooltipProps {
3
3
  /** Short clarifying text — never the only source of an instruction. */
4
4
  label: React.ReactNode;
5
5
  placement?: 'top' | 'bottom' | 'left' | 'right';
6
6
  /** Hover delay in ms. Keyboard focus always shows it immediately. */
7
7
  delay?: number;
8
- /** A single focusable element (Button, IconButton, Link). */
8
+ /**
9
+ * Anything — a Button, a Badge, a span, plain text.
10
+ *
11
+ * A child that cannot take focus on its own is made focusable for you. That is the point: a
12
+ * tooltip on something unreachable by keyboard is invisible to anyone not using a mouse, and it
13
+ * fails silently — a dead tooltip is indistinguishable from a live one until somebody hovers it.
14
+ */
9
15
  children: React.ReactNode;
10
16
  }
17
+ /**
18
+ * Explains something without adding a step. Shows on hover after `delay`, and immediately on
19
+ * keyboard focus.
20
+ *
21
+ * Never put an instruction here that is not available elsewhere: there is no hover on touch.
22
+ */
11
23
  export declare function Tooltip({ label, placement, delay, children }: TooltipProps): React.JSX.Element;
12
24
  //# sourceMappingURL=Tooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAGpC,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAChD,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAiB,EAAE,KAAW,EAAE,QAAQ,EAAE,EAAE,YAAY,qBAUxF"}
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAChD,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAiB,EAAE,KAAW,EAAE,QAAQ,EAAE,EAAE,YAAY,qBAwBxF"}
@@ -1,4 +1,4 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
2
  export interface InputProps {
3
3
  label?: React.ReactNode;
4
4
  value?: string;
@@ -16,6 +16,24 @@ export interface InputProps {
16
16
  icon?: string;
17
17
  /** Trailing static text: unit, currency, "of 40". */
18
18
  suffix?: React.ReactNode;
19
+ /**
20
+ * Adds a clear affordance once the field has a value.
21
+ *
22
+ * Use it on every search field. `type="search"` gets one from the browser for free, but only in
23
+ * Chrome and Safari, and it cannot be styled or sized — Pire hides that one so a search box does
24
+ * not look different per browser. This is the replacement, and it is a real button: focusable,
25
+ * labelled, and the same shape everywhere.
26
+ *
27
+ * Works controlled or uncontrolled.
28
+ */
29
+ isClearable?: boolean;
30
+ /**
31
+ * The clear button's visible text. Defaults to the dictionary's `inputClear`.
32
+ *
33
+ * Deliberately a word rather than an icon: an "x" beside a dialog's own close "x" reads as a
34
+ * second way to dismiss the dialog. Keep it short — it sits inside the field.
35
+ */
36
+ clearLabel?: string;
19
37
  /** Help text below the field. Replaced by errorMessage when invalid. */
20
38
  description?: React.ReactNode;
21
39
  errorMessage?: React.ReactNode;
@@ -35,4 +53,4 @@ export interface InputProps {
35
53
  }
36
54
  /** Single-line text entry. Labels, descriptions and errors are wired to the input by React Aria,
37
55
  * so no manual aria-describedby is ever needed. */
38
- export declare function Input({ label, icon, suffix, description, errorMessage, size, numeric, fullWidth, className, style, inputRef, onChange, ...rest }: InputProps): React.JSX.Element;
56
+ export declare function Input({ label, icon, suffix, description, errorMessage, size, numeric, isClearable, clearLabel, fullWidth, className, style, inputRef, onChange, ...rest }: InputProps): React.JSX.Element;
@@ -1,4 +1,4 @@
1
- import type * as React from 'react';
1
+ import * as React from 'react';
2
2
  export interface InputProps {
3
3
  label?: React.ReactNode;
4
4
  value?: string;
@@ -16,6 +16,24 @@ export interface InputProps {
16
16
  icon?: string;
17
17
  /** Trailing static text: unit, currency, "of 40". */
18
18
  suffix?: React.ReactNode;
19
+ /**
20
+ * Adds a clear affordance once the field has a value.
21
+ *
22
+ * Use it on every search field. `type="search"` gets one from the browser for free, but only in
23
+ * Chrome and Safari, and it cannot be styled or sized — Pire hides that one so a search box does
24
+ * not look different per browser. This is the replacement, and it is a real button: focusable,
25
+ * labelled, and the same shape everywhere.
26
+ *
27
+ * Works controlled or uncontrolled.
28
+ */
29
+ isClearable?: boolean;
30
+ /**
31
+ * The clear button's visible text. Defaults to the dictionary's `inputClear`.
32
+ *
33
+ * Deliberately a word rather than an icon: an "x" beside a dialog's own close "x" reads as a
34
+ * second way to dismiss the dialog. Keep it short — it sits inside the field.
35
+ */
36
+ clearLabel?: string;
19
37
  /** Help text below the field. Replaced by errorMessage when invalid. */
20
38
  description?: React.ReactNode;
21
39
  errorMessage?: React.ReactNode;
@@ -35,5 +53,5 @@ export interface InputProps {
35
53
  }
36
54
  /** Single-line text entry. Labels, descriptions and errors are wired to the input by React Aria,
37
55
  * so no manual aria-describedby is ever needed. */
38
- export declare function Input({ label, icon, suffix, description, errorMessage, size, numeric, fullWidth, className, style, inputRef, onChange, ...rest }: InputProps): React.JSX.Element;
56
+ export declare function Input({ label, icon, suffix, description, errorMessage, size, numeric, isClearable, clearLabel, fullWidth, className, style, inputRef, onChange, ...rest }: InputProps): React.JSX.Element;
39
57
  //# sourceMappingURL=Input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAKpC,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,CAAC;IACpF,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,wEAAwE;IACxE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;CACxC;AAED;oDACoD;AACpD,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,IAAW,EAAE,OAAO,EAC1F,SAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,qBAmB9E"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,CAAC;IACpF,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;CACxC;AAED;oDACoD;AACpD,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,IAAW,EAAE,OAAO,EAC1F,WAAW,EAAE,UAAU,EAAE,SAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,qBAyCvG"}
@@ -1 +1 @@
1
- {"version":3,"file":"ValueHelpDialog.d.ts","sourceRoot":"","sources":["../../../src/components/patterns/ValueHelpDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpE,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,GAAG;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,sDAAsD;IACtD,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACX,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kGAAkG;IAClG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAChF,OAAY,EAAE,IAAS,EAAE,iBAAiB,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EACtF,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,qBAkCpE"}
1
+ {"version":3,"file":"ValueHelpDialog.d.ts","sourceRoot":"","sources":["../../../src/components/patterns/ValueHelpDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpE,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,GAAG;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,sDAAsD;IACtD,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACX,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kGAAkG;IAClG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAChF,OAAY,EAAE,IAAS,EAAE,iBAAiB,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EACtF,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,qBAmCpE"}
@@ -105,6 +105,19 @@
105
105
  .pire-input[data-numeric="true"]{font:var(--type-numeric);text-align:right;font-variant-numeric:tabular-nums}
106
106
  .pire-input::placeholder{color:var(--text-tertiary)}
107
107
  .pire-affix{font:var(--type-caption);color:var(--text-secondary);flex:0 0 auto}
108
+ /* Chrome and Safari decorate type="search" with their own clear button. It cannot be styled or
109
+ sized, Firefox does not draw one at all, and it ignores every token here — so a search box would
110
+ look different per browser. Hidden everywhere; `isClearable` is the replacement, and it is a real
111
+ labelled button rather than a browser affordance. */
112
+ .pire-input::-webkit-search-cancel-button{display:none}
113
+ /* A word, not an icon. An icon-only "x" inside a dialog sits beside the dialog's own close "x" and
114
+ reads as a second way to dismiss it; the label says what is being cleared. Sized down so it
115
+ belongs to the field rather than competing with it. */
116
+ .pire-input-clear{flex:0 0 auto;border:0;background:transparent;padding:0 var(--sp-1);font:var(--type-caption);color:var(--text-link);cursor:pointer;border-radius:var(--radius-1);white-space:nowrap;transition:var(--transition-control)}
117
+ .pire-input-clear[data-hovered]{color:var(--text-link-hover);text-decoration:underline}
118
+ /* `.pire-control :focus-visible` clears inner rings so the control shows a single one. This button
119
+ is a separate target inside it, so it keeps its own. */
120
+ .pire-input-clear[data-focus-visible]{outline:var(--focus-w) solid var(--focus-color);outline-offset:1px}
108
121
  .pire-leading-icon{color:var(--text-tertiary);flex:0 0 auto}
109
122
  /* The shell is fixed-height by default because every single-line control is. Controls whose
110
123
  content sets the height (TextArea, MultiComboBox's chips) opt out with data-multiline and
@@ -270,6 +283,10 @@
270
283
  .pire-progress[data-status="positive"] .pire-progress-fill{background:var(--status-positive-fg)}
271
284
  .pire-progress[data-status="critical"] .pire-progress-fill{background:var(--status-critical-fg)}
272
285
  .pire-progress[data-status="negative"] .pire-progress-fill{background:var(--status-negative-fg)}
286
+ /* A tooltip target takes focus so the tip is reachable by keyboard, and React Aria sets only
287
+ `tabindex` on it — no `data-focus-visible`. The ring therefore lives here rather than relying on
288
+ base.css's `[tabindex]:focus-visible`, which a consumer skipping the resets would not have. */
289
+ .pire-tooltip-target:focus-visible{outline:var(--focus-w) solid var(--focus-color);outline-offset:var(--focus-offset)}
273
290
  .pire-tooltip{max-width:240px;padding:var(--sp-1) var(--sp-2);border-radius:var(--radius-1);background:var(--gray-90);color:var(--text-inverse);font:var(--type-caption);box-shadow:var(--shadow-2);animation:pire-fade-in var(--dur-fast) var(--ease-entrance)}
274
291
 
275
292
  /* ---- Skeleton ---------------------------------------------------------- */
@@ -317,6 +334,22 @@
317
334
  top-to-bottom in source order rather than relying on specificity alone. */
318
335
  .pire-table[data-density="condensed"] .pire-th,.pire-table[data-density="condensed"] .pire-td{padding:0 var(--sp-2)}
319
336
  .pire-table-empty{padding:var(--sp-10);text-align:center;color:var(--text-secondary)}
337
+ /* A disabled row is present for context but cannot be acted on. It recedes rather than
338
+ disappearing, and drops the pointer cue so the row does not look pressable. */
339
+ .pire-tr[data-disabled]{color:var(--text-disabled);cursor:default}
340
+ .pire-tr[data-disabled] .pire-td{color:var(--text-disabled)}
341
+ .pire-tr[data-disabled][data-hovered]{background:transparent}
342
+ /* Detail rows sit under their record and read as part of it: sunken, no bottom rule between the
343
+ two, and free of the fixed row height since the content decides how tall they are. */
344
+ .pire-tr-expanded{height:auto;background:var(--surface-sunken);border-bottom:1px solid var(--border-subtle)}
345
+ .pire-tr-expanded[data-hovered]{background:var(--surface-sunken)}
346
+ .pire-td-expanded{padding:var(--sp-3);color:var(--text-primary);white-space:normal;outline:none}
347
+ /* Totals. `position:sticky` keeps them in view while the body scrolls, which is the whole reason
348
+ they are in a <tfoot> rather than under the table. */
349
+ .pire-tfoot .pire-tr-footer{height:var(--row-h-regular);background:var(--surface-sunken)}
350
+ .pire-tf{position:sticky;bottom:0;padding:0 var(--sp-3);background:var(--surface-sunken);border-top:1px solid var(--border-default);font:var(--type-body-strong);color:var(--text-primary);white-space:nowrap;outline:none}
351
+ .pire-tf[data-numeric="true"]{font:var(--type-numeric);font-weight:600;font-variant-numeric:tabular-nums;text-align:right}
352
+ .pire-table[data-density="condensed"] .pire-td-expanded,.pire-table[data-density="condensed"] .pire-tf{padding-inline:var(--sp-2)}
320
353
  .pire-kpi{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-4);background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-2);text-align:left;min-width:0;transition:var(--transition-surface)}
321
354
  .pire-kpi[data-pressable="true"]{cursor:pointer}
322
355
  .pire-kpi[data-hovered]{box-shadow:var(--shadow-2)}
@@ -678,14 +711,20 @@
678
711
  /* The triggers sit inside .pire-control, flush with its trailing edge. `stretch` makes them the
679
712
  control's full height whatever the size, and the negative margins cancel the control's own
680
713
  padding and gap so there is no seam between the input and the first button. */
681
- .pire-valuehelp-actions{display:flex;align-items:stretch;align-self:stretch;margin-inline-start:calc(var(--sp-2) * -1);margin-inline-end:calc(var(--control-pad-x) * -1)}
714
+ /* Two things have to give for the buttons to fill the control. `.pire-affix` is a block whose
715
+ default alignment centres it — right for the unit strings it usually holds, wrong here — so it
716
+ stretches and becomes a flex parent; without both, the buttons collapse to their 20px content
717
+ height and float in the middle of a 40px control. */
718
+ .pire-control:has(.pire-valuehelp-actions) .pire-affix{align-self:stretch;display:flex}
719
+ .pire-valuehelp-actions{display:flex;align-items:stretch;margin-inline-start:calc(var(--sp-2) * -1);margin-inline-end:calc(var(--control-pad-x) * -1)}
682
720
  .pire-valuehelp-actions .pire-iconbtn{height:auto;border-radius:0;border-inline-start:1px solid var(--border-field)}
683
- /* Only the last button rounds, so the group follows the control's own corner instead of cutting it. */
684
- .pire-valuehelp-actions .pire-iconbtn:last-child{border-start-end-radius:var(--radius-1);border-end-end-radius:var(--radius-1)}
685
- /* `.pire-control :focus-visible` clears inner rings so the whole control shows one. That is right
686
- with a single input, but here two buttons share the control and the outer ring cannot say which
687
- is focused so each gets its own, drawn inside its own box. */
688
- .pire-valuehelp-actions .pire-iconbtn[data-focus-visible]{outline:var(--focus-w) solid var(--focus-color);outline-offset:calc(var(--focus-w) * -1)}
721
+ /* The control's *inner* corner is its radius less its border, so matching --radius-1 exactly would
722
+ leave the button proud of the curve by a pixel. Only the last button rounds. */
723
+ .pire-valuehelp-actions .pire-iconbtn:last-child{border-start-end-radius:calc(var(--radius-1) - 1px);border-end-end-radius:calc(var(--radius-1) - 1px)}
724
+ /* A tint rather than a ring. The control already rings on focus-within, so focus is visible; what
725
+ that ring cannot say is *which* of two buttons has it. An inset outline said so but collided
726
+ with the control's own border and read as a doubled edge. */
727
+ .pire-valuehelp-actions .pire-iconbtn[data-focus-visible]{outline:none;background:var(--surface-selected);color:var(--accent-subtle-fg)}
689
728
 
690
729
  /* ---- Icon --------------------------------------------------------------- */
691
730
  /* Development-only marker for a name that resolved to no glyph. Rendered by Icon in dev builds
@@ -722,9 +761,8 @@
722
761
  sitting among other controls, the ring is what says which one is live. */
723
762
  .pire-cp-input:focus-visible{outline:none}
724
763
  .pire-cp-input::placeholder{font:var(--type-body);color:var(--text-tertiary)}
725
- /* React Aria's SearchField renders type="search", which Chrome decorates with its own clear
726
- affordance. It cannot be styled, does not exist in Firefox, and ignores every token here, so a
727
- design system is better off without it. Escape closes the palette. */
764
+ /* Same reasoning as `.pire-input`'s rule: the browser's own search decoration is unstyleable and
765
+ Chrome/Safari-only. The palette needs no replacement Escape closes it outright. */
728
766
  .pire-cp-input::-webkit-search-cancel-button{display:none}
729
767
  .pire-cp-list{flex:1;min-height:0;overflow:auto;padding:var(--sp-1) 0;outline:none;display:flex;flex-direction:column}
730
768
  /* Explicitly a column: the section is a flex child of .pire-cp-list, and leaving it as a block
@@ -21,6 +21,8 @@ export interface PireMessages {
21
21
  dataTableSelectRow: string;
22
22
  /** Announced while the table body is a skeleton. */
23
23
  dataTableLoading: string;
24
+ /** Row header announced for the totals row when the first column carries no summary cell. */
25
+ dataTableSummaryRow: string;
24
26
  /** Accessible name of the dialog's close affordance. */
25
27
  dialogClose: string;
26
28
  /** Accessible name of SidePanel's close affordance. */
@@ -48,6 +50,8 @@ export interface PireMessages {
48
50
  numberFieldIncrease: string;
49
51
  numberFieldDecrease: string;
50
52
  /** Accessible name of the button that clears a ValueHelpField. */
53
+ /** Accessible name of the clear affordance on a clearable Input. */
54
+ inputClear: string;
51
55
  /** Placeholder in the closed value-help field when nothing is picked. */
52
56
  valueHelpFieldPlaceholder: string;
53
57
  valueHelpFieldClear: string;
@@ -21,6 +21,8 @@ export interface PireMessages {
21
21
  dataTableSelectRow: string;
22
22
  /** Announced while the table body is a skeleton. */
23
23
  dataTableLoading: string;
24
+ /** Row header announced for the totals row when the first column carries no summary cell. */
25
+ dataTableSummaryRow: string;
24
26
  /** Accessible name of the dialog's close affordance. */
25
27
  dialogClose: string;
26
28
  /** Accessible name of SidePanel's close affordance. */
@@ -48,6 +50,8 @@ export interface PireMessages {
48
50
  numberFieldIncrease: string;
49
51
  numberFieldDecrease: string;
50
52
  /** Accessible name of the button that clears a ValueHelpField. */
53
+ /** Accessible name of the clear affordance on a clearable Input. */
54
+ inputClear: string;
51
55
  /** Placeholder in the closed value-help field when nothing is picked. */
52
56
  valueHelpFieldPlaceholder: string;
53
57
  valueHelpFieldClear: string;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}