@longline/aqua-ui 1.0.343 → 1.0.345

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.
@@ -19,6 +19,14 @@ interface IChipProps extends ITestable {
19
19
  * omit the parameter.
20
20
  */
21
21
  onClick: (e: React.MouseEvent | React.KeyboardEvent) => void;
22
+ /**
23
+ * Optional: makes the chip's **content** (everything but the X button)
24
+ * interactive. Triggered when the content is clicked, or when Enter/Space is
25
+ * pressed while the `Chip` has focus — use it for an "edit this chip" action
26
+ * that is distinct from removal (the X button / Delete / Backspace still call
27
+ * `onClick`). When omitted the content is inert, as before.
28
+ */
29
+ onContentClick?: (e: React.MouseEvent | React.KeyboardEvent) => void;
22
30
  /**
23
31
  * Accessible label for the remove button.
24
32
  * @default "Remove chip"
@@ -38,14 +38,20 @@ var ChipBase = function (props) {
38
38
  e.stopPropagation();
39
39
  props.onClick(e);
40
40
  }
41
+ // When the content is interactive, Enter/Space activate it (edit action).
42
+ if (props.onContentClick && (e.key === 'Enter' || e.key === ' ')) {
43
+ e.preventDefault();
44
+ e.stopPropagation();
45
+ props.onContentClick(e);
46
+ }
41
47
  };
42
48
  return (React.createElement("div", { "data-testid": props['data-testid'] || "Chip", className: props.className, style: props.style, tabIndex: 0, onKeyDown: handleKeyDown, "aria-disabled": props.disabled },
43
- React.createElement("span", { className: "inner" }, props.children),
49
+ React.createElement("span", { className: "inner", role: props.onContentClick ? "button" : undefined, onClick: props.onContentClick && !props.disabled ? props.onContentClick : undefined }, props.children),
44
50
  React.createElement("button", { type: "button", tabIndex: -1, onClick: props.onClick, "aria-label": props.removeLabel, disabled: props.disabled, "aria-disabled": props.disabled },
45
51
  React.createElement("svg", null,
46
52
  React.createElement("use", { xlinkHref: SVG.Icons.Cross })))));
47
53
  };
48
- var ChipStyled = styled(ChipBase)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n // Dimensions:\n min-width: 80px;\n max-width: 150px;\n width: auto;\n height: 24px;\n padding: 0 3px 0 12px;\n\n // Appearance:\n background-color: ", ";\n border: none;\n color: ", ";\n border-radius: 12px;\n user-select: none;\n outline: none;\n\n display: inline-flex;\n align-items: center;\n gap: 4px; // Gap between content and \"X\".\n margin-right: 2px; \n\n // Spacing from previous Chip.\n & + & {\n margin-left: 2px;\n }\n\n font: ", ";\n\n span.inner {\n flex: 1;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: none;\n }\n\n & > button {\n border: none;\n background: transparent;\n outline: none;\n padding: 0;\n margin: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n\n svg {\n transition: fill ", "ms ease-in-out,\n background-color ", "ms ease-in-out;\n fill: ", ";\n box-sizing: border-box;\n width: 18px;\n height: 18px;\n padding: 2px;\n border-radius: 50%;\n cursor: pointer;\n }\n }\n\n &:focus {\n outline: solid 2px ", ";\n }\n\n // When Chip is hovered, svg is colored.\n &:hover {\n & button > svg {\n background-color: ", ";\n fill: ", ";\n }\n }\n\n & > button svg:active {\n background-color: ", ";\n fill: ", ";\n }\n\n ", "\n"], ["\n // Dimensions:\n min-width: 80px;\n max-width: 150px;\n width: auto;\n height: 24px;\n padding: 0 3px 0 12px;\n\n // Appearance:\n background-color: ", ";\n border: none;\n color: ", ";\n border-radius: 12px;\n user-select: none;\n outline: none;\n\n display: inline-flex;\n align-items: center;\n gap: 4px; // Gap between content and \"X\".\n margin-right: 2px; \n\n // Spacing from previous Chip.\n & + & {\n margin-left: 2px;\n }\n\n font: ", ";\n\n span.inner {\n flex: 1;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: none;\n }\n\n & > button {\n border: none;\n background: transparent;\n outline: none;\n padding: 0;\n margin: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n\n svg {\n transition: fill ", "ms ease-in-out,\n background-color ", "ms ease-in-out;\n fill: ", ";\n box-sizing: border-box;\n width: 18px;\n height: 18px;\n padding: 2px;\n border-radius: 50%;\n cursor: pointer;\n }\n }\n\n &:focus {\n outline: solid 2px ", ";\n }\n\n // When Chip is hovered, svg is colored.\n &:hover {\n & button > svg {\n background-color: ", ";\n fill: ", ";\n }\n }\n\n & > button svg:active {\n background-color: ", ";\n fill: ", ";\n }\n\n ", "\n"
54
+ var ChipStyled = styled(ChipBase)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n // Dimensions:\n min-width: 80px;\n max-width: 150px;\n width: auto;\n height: 24px;\n padding: 0 3px 0 12px;\n\n // Appearance:\n background-color: ", ";\n border: none;\n color: ", ";\n border-radius: 12px;\n user-select: none;\n outline: none;\n\n display: inline-flex;\n align-items: center;\n gap: 4px; // Gap between content and \"X\".\n margin-right: 2px; \n\n // Spacing from previous Chip.\n & + & {\n margin-left: 2px;\n }\n\n font: ", ";\n\n span.inner {\n flex: 1;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n // Inert by default; interactive (clickable \"edit\" target) when onContentClick\n // is supplied \u2014 then it accepts pointer events and shows a pointer cursor.\n pointer-events: ", ";\n ", "\n }\n\n & > button {\n border: none;\n background: transparent;\n outline: none;\n padding: 0;\n margin: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n\n svg {\n transition: fill ", "ms ease-in-out,\n background-color ", "ms ease-in-out;\n fill: ", ";\n box-sizing: border-box;\n width: 18px;\n height: 18px;\n padding: 2px;\n border-radius: 50%;\n cursor: pointer;\n }\n }\n\n &:focus {\n outline: solid 2px ", ";\n }\n\n // When Chip is hovered, svg is colored.\n &:hover {\n & button > svg {\n background-color: ", ";\n fill: ", ";\n }\n }\n\n & > button svg:active {\n background-color: ", ";\n fill: ", ";\n }\n\n ", "\n"], ["\n // Dimensions:\n min-width: 80px;\n max-width: 150px;\n width: auto;\n height: 24px;\n padding: 0 3px 0 12px;\n\n // Appearance:\n background-color: ", ";\n border: none;\n color: ", ";\n border-radius: 12px;\n user-select: none;\n outline: none;\n\n display: inline-flex;\n align-items: center;\n gap: 4px; // Gap between content and \"X\".\n margin-right: 2px; \n\n // Spacing from previous Chip.\n & + & {\n margin-left: 2px;\n }\n\n font: ", ";\n\n span.inner {\n flex: 1;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n // Inert by default; interactive (clickable \"edit\" target) when onContentClick\n // is supplied \u2014 then it accepts pointer events and shows a pointer cursor.\n pointer-events: ", ";\n ", "\n }\n\n & > button {\n border: none;\n background: transparent;\n outline: none;\n padding: 0;\n margin: 0;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n\n svg {\n transition: fill ", "ms ease-in-out,\n background-color ", "ms ease-in-out;\n fill: ", ";\n box-sizing: border-box;\n width: 18px;\n height: 18px;\n padding: 2px;\n border-radius: 50%;\n cursor: pointer;\n }\n }\n\n &:focus {\n outline: solid 2px ", ";\n }\n\n // When Chip is hovered, svg is colored.\n &:hover {\n & button > svg {\n background-color: ", ";\n fill: ", ";\n }\n }\n\n & > button svg:active {\n background-color: ", ";\n fill: ", ";\n }\n\n ", "\n"
49
55
  /**
50
56
  * A compact element representing a user input, selection, or filter that can be removed.
51
57
  *
@@ -87,7 +93,7 @@ var ChipStyled = styled(ChipBase)(templateObject_2 || (templateObject_2 = __make
87
93
  * Adjacent `Chip` siblings are automatically spaced with a small gap.
88
94
  * No additional margin styling is needed when placing chips side by side.
89
95
  */
90
- ])), function (p) { return p.theme.colors.neutral[10]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.font.labelSmall; }, function (p) { return p.theme.animation.duration; }, function (p) { return p.theme.animation.duration; }, function (p) { return p.theme.colors.neutral[50]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.primary[2]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.disabled && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n pointer-events: none;\n cursor: auto;\n background-color: ", ";\n color: ", ";\n & > button svg {\n fill: ", ";\n }\n "], ["\n pointer-events: none;\n cursor: auto;\n background-color: ", ";\n color: ", ";\n & > button svg {\n fill: ", ";\n }\n "])), function (p) { return p.theme.colors.neutral[50]; }, function (p) { return p.theme.colors.primary[3]; }, function (p) { return p.theme.colors.primary[3]; }); });
96
+ ])), function (p) { return p.theme.colors.neutral[10]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.font.labelSmall; }, function (p) { return p.onContentClick ? 'auto' : 'none'; }, function (p) { return p.onContentClick && !p.disabled && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n cursor: pointer;\n &:hover { text-decoration: underline; }\n "], ["\n cursor: pointer;\n &:hover { text-decoration: underline; }\n "]))); }, function (p) { return p.theme.animation.duration; }, function (p) { return p.theme.animation.duration; }, function (p) { return p.theme.colors.neutral[50]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.primary[2]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.disabled && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n pointer-events: none;\n cursor: auto;\n background-color: ", ";\n color: ", ";\n & > button svg {\n fill: ", ";\n }\n "], ["\n pointer-events: none;\n cursor: auto;\n background-color: ", ";\n color: ", ";\n & > button svg {\n fill: ", ";\n }\n "])), function (p) { return p.theme.colors.neutral[50]; }, function (p) { return p.theme.colors.primary[3]; }, function (p) { return p.theme.colors.primary[3]; }); });
91
97
  /**
92
98
  * A compact element representing a user input, selection, or filter that can be removed.
93
99
  *
@@ -135,4 +141,4 @@ var Chip = function (_a) {
135
141
  };
136
142
  Chip.displayName = "Chip";
137
143
  export { Chip };
138
- var templateObject_1, templateObject_2;
144
+ var templateObject_1, templateObject_2, templateObject_3;
@@ -4,6 +4,27 @@ interface IListViewProps {
4
4
  * Array of data to show in the table
5
5
  */
6
6
  data: any[] | null | undefined;
7
+ /**
8
+ * Controlled sort key. When `onSortClick` is provided the `ListView` is in
9
+ * **controlled-sort** mode: it does NOT sort `data` itself (the data is assumed
10
+ * already sorted — e.g. server-side/paged), and this key + `reverse` only drive
11
+ * the header's active-sort indicator. Ignored in the default (in-memory sort)
12
+ * mode, where sorting is internal state.
13
+ */
14
+ sort?: string;
15
+ /**
16
+ * Controlled sort direction, paired with `sort` (see it).
17
+ * @default false
18
+ */
19
+ reverse?: boolean;
20
+ /**
21
+ * Fired when a sortable column header is clicked. **Providing this switches the
22
+ * `ListView` to controlled-sort mode** (see `sort`): the `ListView` stops sorting
23
+ * `data` in memory and delegates the decision to you — typically you re-query a
24
+ * server for the newly-sorted page and feed back `sort`/`reverse` + sorted `data`.
25
+ * Without it, header clicks sort `data` in memory (the default).
26
+ */
27
+ onSortClick?: (column: IColumnProps) => void;
7
28
  /**
8
29
  * If set, show no header.
9
30
  * @default false
@@ -61,26 +61,38 @@ var getColumns = function (children) {
61
61
  return getChildrenOfTypeDeep(children, ListView.Column).map(function (c) { return c.props; });
62
62
  };
63
63
  var ListViewBase = function (props) {
64
- var _a, _b, _c;
64
+ var _a, _b, _c, _d, _e;
65
65
  var children = props.children, otherProps = __rest(props, ["children"]);
66
- var _d = React.useState(false), columnsMode = _d[0], setColumnsMode = _d[1];
66
+ var _f = React.useState(false), columnsMode = _f[0], setColumnsMode = _f[1];
67
67
  var originalColumns = getColumns(props.children);
68
- var _e = React.useState(originalColumns), columns = _e[0], setColumns = _e[1];
68
+ var _g = React.useState(originalColumns), columns = _g[0], setColumns = _g[1];
69
69
  // Find default sort column:
70
70
  var sortColumn = (_a = columns.find(function (c) { return c.defaultSort; })) !== null && _a !== void 0 ? _a : columns[0];
71
- var _f = React.useState((_b = sortColumn === null || sortColumn === void 0 ? void 0 : sortColumn.sort) !== null && _b !== void 0 ? _b : ''), sort = _f[0], setSort = _f[1];
72
- var _g = React.useState((_c = sortColumn === null || sortColumn === void 0 ? void 0 : sortColumn.reverse) !== null && _c !== void 0 ? _c : false), reverse = _g[0], setReverse = _g[1];
73
- var _h = React.useState(null), data = _h[0], setData = _h[1];
71
+ // Controlled-sort mode: when the consumer supplies onSortClick, it owns the sort
72
+ // (typically sorting server-side and feeding back pre-sorted data + sort/reverse).
73
+ var controlled = !!props.onSortClick;
74
+ // Internal sort state, used only in the default (uncontrolled) in-memory mode.
75
+ var _h = React.useState((_b = sortColumn === null || sortColumn === void 0 ? void 0 : sortColumn.sort) !== null && _b !== void 0 ? _b : ''), sortState = _h[0], setSortState = _h[1];
76
+ var _j = React.useState((_c = sortColumn === null || sortColumn === void 0 ? void 0 : sortColumn.reverse) !== null && _c !== void 0 ? _c : false), reverseState = _j[0], setReverseState = _j[1];
77
+ var _k = React.useState(null), data = _k[0], setData = _k[1];
78
+ // The active sort key/direction: from props when controlled, else internal state.
79
+ var sort = controlled ? ((_d = props.sort) !== null && _d !== void 0 ? _d : '') : sortState;
80
+ var reverse = controlled ? ((_e = props.reverse) !== null && _e !== void 0 ? _e : false) : reverseState;
74
81
  React.useEffect(function () {
75
82
  // Don't sort if no data is available yet:
76
83
  if (!Array.isArray(props.data))
77
84
  return;
85
+ // Controlled: the data is assumed already sorted (e.g. server-side) — show as-is.
86
+ if (controlled) {
87
+ setData(props.data);
88
+ return;
89
+ }
78
90
  // Find the column corresponding to the current sort key. If none matches
79
91
  // (e.g. no sortable column and no defaultSort), show the data unsorted
80
92
  // rather than rendering nothing.
81
- var sortColumn = columns.find(function (c) { return c.sort === sort; });
82
- setData(sortColumn ? sortItems(props.data, sort, reverse, sortColumn.sortValue) : props.data);
83
- }, [props.data, sort, reverse, columns]);
93
+ var sc = columns.find(function (c) { return c.sort === sort; });
94
+ setData(sc ? sortItems(props.data, sort, reverse, sc.sortValue) : props.data);
95
+ }, [props.data, sort, reverse, columns, controlled]);
84
96
  // If children change, then update columns state.
85
97
  React.useEffect(function () {
86
98
  setColumns(getColumns(props.children));
@@ -88,12 +100,17 @@ var ListViewBase = function (props) {
88
100
  // Change sort:
89
101
  var handleSort = function (column) {
90
102
  var _a, _b;
91
- if (sort === column.sort) {
92
- setReverse(!reverse);
103
+ // Controlled: delegate to the consumer (who re-queries and re-feeds data).
104
+ if (props.onSortClick) {
105
+ props.onSortClick(column);
106
+ return;
107
+ }
108
+ if (sortState === column.sort) {
109
+ setReverseState(!reverseState);
93
110
  }
94
111
  else {
95
- setSort((_a = column.sort) !== null && _a !== void 0 ? _a : '');
96
- setReverse((_b = column.reverse) !== null && _b !== void 0 ? _b : false);
112
+ setSortState((_a = column.sort) !== null && _a !== void 0 ? _a : '');
113
+ setReverseState((_b = column.reverse) !== null && _b !== void 0 ? _b : false);
97
114
  }
98
115
  };
99
116
  var handleCheck = function (data, item) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longline/aqua-ui",
3
- "version": "1.0.343",
3
+ "version": "1.0.345",
4
4
  "description": "AquaUI",
5
5
  "author": "Alexander van Oostenrijk / Longline Environment",
6
6
  "license": "Commercial",