@guardian/stand 0.0.50 → 0.0.52

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 (88) hide show
  1. package/dist/Modal.cjs +7 -0
  2. package/dist/Modal.d.cts +5 -0
  3. package/dist/Modal.d.ts +5 -0
  4. package/dist/Modal.js +3 -0
  5. package/dist/TagPicker.cjs +4 -2
  6. package/dist/TagPicker.d.cts +3 -2
  7. package/dist/TagPicker.d.ts +3 -2
  8. package/dist/TagPicker.js +3 -2
  9. package/dist/components/Form/Form.cjs +1 -0
  10. package/dist/components/Form/Form.js +1 -0
  11. package/dist/components/InlineMessage/InlineMessage.cjs +2 -1
  12. package/dist/components/InlineMessage/InlineMessage.d.cts +1 -0
  13. package/dist/components/InlineMessage/InlineMessage.d.ts +1 -0
  14. package/dist/components/InlineMessage/InlineMessage.js +2 -1
  15. package/dist/components/InlineMessage/types.d.cts +5 -0
  16. package/dist/components/InlineMessage/types.d.ts +5 -0
  17. package/dist/components/Modal/Modal.cjs +97 -0
  18. package/dist/components/Modal/Modal.d.cts +21 -0
  19. package/dist/components/Modal/Modal.d.ts +21 -0
  20. package/dist/components/Modal/Modal.js +93 -0
  21. package/dist/components/Modal/styles.cjs +100 -0
  22. package/dist/components/Modal/styles.d.cts +10 -0
  23. package/dist/components/Modal/styles.d.ts +10 -0
  24. package/dist/components/Modal/styles.js +92 -0
  25. package/dist/components/Modal/types.d.cts +20 -0
  26. package/dist/components/Modal/types.d.ts +20 -0
  27. package/dist/components/Select/Select.cjs +3 -1
  28. package/dist/components/Select/Select.d.cts +2 -0
  29. package/dist/components/Select/Select.d.ts +2 -0
  30. package/dist/components/Select/Select.js +3 -1
  31. package/dist/components/Select/types.d.cts +15 -2
  32. package/dist/components/Select/types.d.ts +15 -2
  33. package/dist/components/TagPicker/Autocomplete.cjs +60 -48
  34. package/dist/components/TagPicker/Autocomplete.d.cts +12 -2
  35. package/dist/components/TagPicker/Autocomplete.d.ts +12 -2
  36. package/dist/components/TagPicker/Autocomplete.js +63 -51
  37. package/dist/components/TagPicker/TagPicker.cjs +105 -0
  38. package/dist/components/TagPicker/TagPicker.d.cts +91 -0
  39. package/dist/components/TagPicker/TagPicker.d.ts +91 -0
  40. package/dist/components/TagPicker/TagPicker.js +105 -0
  41. package/dist/components/TagPicker/TagSearchWithFilters.cjs +53 -0
  42. package/dist/components/TagPicker/TagSearchWithFilters.js +53 -0
  43. package/dist/components/TagPicker/TagTable.cjs +10 -49
  44. package/dist/components/TagPicker/TagTable.d.cts +12 -48
  45. package/dist/components/TagPicker/TagTable.d.ts +12 -48
  46. package/dist/components/TagPicker/TagTable.js +29 -68
  47. package/dist/components/TagPicker/styles.cjs +64 -3
  48. package/dist/components/TagPicker/styles.js +59 -4
  49. package/dist/components/TagPicker/types.d.cts +5 -1
  50. package/dist/components/TagPicker/types.d.ts +5 -1
  51. package/dist/components/Typography/Typography.cjs +7 -4
  52. package/dist/components/Typography/Typography.d.cts +1 -5
  53. package/dist/components/Typography/Typography.d.ts +1 -5
  54. package/dist/components/Typography/Typography.js +7 -4
  55. package/dist/components/Typography/types.d.cts +3 -2
  56. package/dist/components/Typography/types.d.ts +3 -2
  57. package/dist/components/UserMenu/PreferenceRadioGroup.js +5 -5
  58. package/dist/index.cjs +2 -0
  59. package/dist/index.d.cts +4 -3
  60. package/dist/index.d.ts +4 -3
  61. package/dist/index.js +2 -1
  62. package/dist/styleD/build/css/component/autocomplete.css +3 -0
  63. package/dist/styleD/build/css/component/modal.css +51 -0
  64. package/dist/styleD/build/css/component/tagPicker.css +11 -0
  65. package/dist/styleD/build/css/component/tagTable.css +2 -2
  66. package/dist/styleD/build/typescript/component/autocomplete.cjs +5 -0
  67. package/dist/styleD/build/typescript/component/autocomplete.d.cts +5 -0
  68. package/dist/styleD/build/typescript/component/autocomplete.d.ts +5 -0
  69. package/dist/styleD/build/typescript/component/autocomplete.js +5 -0
  70. package/dist/styleD/build/typescript/component/intendedAudienceSignifier.cjs +4 -1
  71. package/dist/styleD/build/typescript/component/intendedAudienceSignifier.d.cts +1 -0
  72. package/dist/styleD/build/typescript/component/intendedAudienceSignifier.d.ts +1 -0
  73. package/dist/styleD/build/typescript/component/intendedAudienceSignifier.js +4 -1
  74. package/dist/styleD/build/typescript/component/modal.cjs +72 -0
  75. package/dist/styleD/build/typescript/component/modal.d.cts +75 -0
  76. package/dist/styleD/build/typescript/component/modal.d.ts +75 -0
  77. package/dist/styleD/build/typescript/component/modal.js +72 -0
  78. package/dist/styleD/build/typescript/component/tagPicker.cjs +17 -0
  79. package/dist/styleD/build/typescript/component/tagPicker.d.cts +20 -0
  80. package/dist/styleD/build/typescript/component/tagPicker.d.ts +20 -0
  81. package/dist/styleD/build/typescript/component/tagPicker.js +17 -0
  82. package/dist/styleD/build/typescript/component/tagTable.cjs +2 -2
  83. package/dist/styleD/build/typescript/component/tagTable.js +2 -2
  84. package/package.json +16 -2
  85. package/dist/components/TagPicker/TagAutocomplete.cjs +0 -118
  86. package/dist/components/TagPicker/TagAutocomplete.d.cts +0 -144
  87. package/dist/components/TagPicker/TagAutocomplete.d.ts +0 -144
  88. package/dist/components/TagPicker/TagAutocomplete.js +0 -118
@@ -0,0 +1,91 @@
1
+ import { DeepPartial } from "../../util/types.cjs";
2
+ import { ComponentSelect } from "../../styleD/build/typescript/component/select.cjs";
3
+ import { ComponentAutocomplete } from "../../styleD/build/typescript/component/autocomplete.cjs";
4
+ import { ComponentTagTable } from "../../styleD/build/typescript/component/tagTable.cjs";
5
+ import { FilterOption, TagRow } from "./types.cjs";
6
+ import { ComponentTagPicker } from "../../styleD/build/typescript/component/tagPicker.cjs";
7
+ import { SerializedStyles } from "@emotion/react";
8
+ import { ReactElement } from "react";
9
+
10
+ //#region src/components/TagPicker/TagPicker.d.ts
11
+ type TagPickerProps<T extends TagRow = TagRow> = {
12
+ /** `addTag` - Function called when a tag is selected from the dropdown or proposal list */addTag: (tag: T) => void; /** `loading` - Whether the component is loading options for the dropdown */
13
+ loading: boolean; /** `offline` - Whether the component has failed to fetch a list of options, indicating either that the service is offline or cannot be reached */
14
+ offline?: boolean; /** `onReorder - Function called when a selected tag is moved in the tag table */
15
+ onReorder?: (tags: T[]) => void; /** `onReorder - Function called the user enters a query or selects a filter value */
16
+ onSearch: (queryText: string, filterValue?: string) => void; /** `options` - The list of options shown in the dropdown */
17
+ options: T[]; /** `proposedTags` - A list of "proposed tags" that the user can add */
18
+ proposedTags: T[]; /** `readOnly` - Whether the interactions modifying the list of tags should be disabled */
19
+ readOnly?: boolean; /** `addTag` - Function called when a tag is removed from selected tags list */
20
+ removeTag: (tag: T) => void; /** `retryConnection - Function called to check if the service to fetch tag options is available again */
21
+ retryConnection?: () => void; /** `tags` - The list of selected tags */
22
+ tags: T[]; /** `canRemove - A filter function that determines if the user is able to remove the tag from the selected tags */
23
+ canRemove?: (tag: T) => boolean; /** `filterRows - A filter function that determines if the tag should be excluded from the selected and proposed tag tables */
24
+ filterRows?: (tag: T) => boolean; /** `filterOptions` - the list of options for setting the filter value (second argument of `onSearch`). If omitted, or has only one member, the Select input is not rendered. */
25
+ filterOptions?: FilterOption[]; /** `offlineBackupTags` - A list of tags that the user can select if the service is offline */
26
+ offlineBackupTags?: T[];
27
+ highlightLeadingTag?: boolean;
28
+ searchPlaceholder?: string;
29
+ searchLabel?: string;
30
+ removeIcon?: ReactElement;
31
+ searchIcon?: ReactElement;
32
+ showTagType?: boolean;
33
+ showTagSectionName?: boolean; /** `theme` - Used to customise the look and feel of the TagPicker component */
34
+ theme?: DeepPartial<ComponentTagPicker>;
35
+ tagTableTheme?: DeepPartial<ComponentTagTable>;
36
+ proposedTagTableTheme?: DeepPartial<ComponentTagTable>;
37
+ autoCompleteTheme?: DeepPartial<ComponentAutocomplete>;
38
+ selectTheme?: DeepPartial<ComponentSelect>; /** `cssOverrides` - Escape hatch for styling that doesn't fall into the theme */
39
+ cssOverrides?: SerializedStyles;
40
+ };
41
+ /**
42
+ * ## TagPicker
43
+ *
44
+ * *Status: Testing*
45
+ *
46
+ * **Peer dependencies:**
47
+ * - `react-aria-components`
48
+ *
49
+ * See the `peerDependencies` section of the `package.json` for compatible versions to install.
50
+ *
51
+ *
52
+ * #### Props
53
+ *
54
+ * See {@link TagPickerProps} for a full list of props and descriptions.
55
+ *
56
+ * #### Example
57
+ *
58
+ * This is currently still in testing phase, so a production implementation is not yet available.
59
+ */
60
+ declare function TagPicker<T extends TagRow = TagRow>({
61
+ addTag,
62
+ loading,
63
+ offline,
64
+ onReorder,
65
+ onSearch,
66
+ options,
67
+ proposedTags,
68
+ readOnly,
69
+ removeTag,
70
+ retryConnection,
71
+ tags,
72
+ canRemove,
73
+ filterRows,
74
+ filterOptions,
75
+ offlineBackupTags,
76
+ highlightLeadingTag,
77
+ searchPlaceholder,
78
+ searchLabel,
79
+ removeIcon,
80
+ searchIcon,
81
+ showTagType,
82
+ showTagSectionName,
83
+ theme,
84
+ tagTableTheme,
85
+ proposedTagTableTheme,
86
+ autoCompleteTheme,
87
+ selectTheme,
88
+ cssOverrides
89
+ }: TagPickerProps<T>): import("@emotion/react/jsx-runtime").JSX.Element;
90
+ //#endregion
91
+ export { TagPicker };
@@ -0,0 +1,91 @@
1
+ import { DeepPartial } from "../../util/types.js";
2
+ import { ComponentSelect } from "../../styleD/build/typescript/component/select.js";
3
+ import { ComponentAutocomplete } from "../../styleD/build/typescript/component/autocomplete.js";
4
+ import { ComponentTagTable } from "../../styleD/build/typescript/component/tagTable.js";
5
+ import { FilterOption, TagRow } from "./types.js";
6
+ import { ComponentTagPicker } from "../../styleD/build/typescript/component/tagPicker.js";
7
+ import { ReactElement } from "react";
8
+ import { SerializedStyles } from "@emotion/react";
9
+
10
+ //#region src/components/TagPicker/TagPicker.d.ts
11
+ type TagPickerProps<T extends TagRow = TagRow> = {
12
+ /** `addTag` - Function called when a tag is selected from the dropdown or proposal list */addTag: (tag: T) => void; /** `loading` - Whether the component is loading options for the dropdown */
13
+ loading: boolean; /** `offline` - Whether the component has failed to fetch a list of options, indicating either that the service is offline or cannot be reached */
14
+ offline?: boolean; /** `onReorder - Function called when a selected tag is moved in the tag table */
15
+ onReorder?: (tags: T[]) => void; /** `onReorder - Function called the user enters a query or selects a filter value */
16
+ onSearch: (queryText: string, filterValue?: string) => void; /** `options` - The list of options shown in the dropdown */
17
+ options: T[]; /** `proposedTags` - A list of "proposed tags" that the user can add */
18
+ proposedTags: T[]; /** `readOnly` - Whether the interactions modifying the list of tags should be disabled */
19
+ readOnly?: boolean; /** `addTag` - Function called when a tag is removed from selected tags list */
20
+ removeTag: (tag: T) => void; /** `retryConnection - Function called to check if the service to fetch tag options is available again */
21
+ retryConnection?: () => void; /** `tags` - The list of selected tags */
22
+ tags: T[]; /** `canRemove - A filter function that determines if the user is able to remove the tag from the selected tags */
23
+ canRemove?: (tag: T) => boolean; /** `filterRows - A filter function that determines if the tag should be excluded from the selected and proposed tag tables */
24
+ filterRows?: (tag: T) => boolean; /** `filterOptions` - the list of options for setting the filter value (second argument of `onSearch`). If omitted, or has only one member, the Select input is not rendered. */
25
+ filterOptions?: FilterOption[]; /** `offlineBackupTags` - A list of tags that the user can select if the service is offline */
26
+ offlineBackupTags?: T[];
27
+ highlightLeadingTag?: boolean;
28
+ searchPlaceholder?: string;
29
+ searchLabel?: string;
30
+ removeIcon?: ReactElement;
31
+ searchIcon?: ReactElement;
32
+ showTagType?: boolean;
33
+ showTagSectionName?: boolean; /** `theme` - Used to customise the look and feel of the TagPicker component */
34
+ theme?: DeepPartial<ComponentTagPicker>;
35
+ tagTableTheme?: DeepPartial<ComponentTagTable>;
36
+ proposedTagTableTheme?: DeepPartial<ComponentTagTable>;
37
+ autoCompleteTheme?: DeepPartial<ComponentAutocomplete>;
38
+ selectTheme?: DeepPartial<ComponentSelect>; /** `cssOverrides` - Escape hatch for styling that doesn't fall into the theme */
39
+ cssOverrides?: SerializedStyles;
40
+ };
41
+ /**
42
+ * ## TagPicker
43
+ *
44
+ * *Status: Testing*
45
+ *
46
+ * **Peer dependencies:**
47
+ * - `react-aria-components`
48
+ *
49
+ * See the `peerDependencies` section of the `package.json` for compatible versions to install.
50
+ *
51
+ *
52
+ * #### Props
53
+ *
54
+ * See {@link TagPickerProps} for a full list of props and descriptions.
55
+ *
56
+ * #### Example
57
+ *
58
+ * This is currently still in testing phase, so a production implementation is not yet available.
59
+ */
60
+ declare function TagPicker<T extends TagRow = TagRow>({
61
+ addTag,
62
+ loading,
63
+ offline,
64
+ onReorder,
65
+ onSearch,
66
+ options,
67
+ proposedTags,
68
+ readOnly,
69
+ removeTag,
70
+ retryConnection,
71
+ tags,
72
+ canRemove,
73
+ filterRows,
74
+ filterOptions,
75
+ offlineBackupTags,
76
+ highlightLeadingTag,
77
+ searchPlaceholder,
78
+ searchLabel,
79
+ removeIcon,
80
+ searchIcon,
81
+ showTagType,
82
+ showTagSectionName,
83
+ theme,
84
+ tagTableTheme,
85
+ proposedTagTableTheme,
86
+ autoCompleteTheme,
87
+ selectTheme,
88
+ cssOverrides
89
+ }: TagPickerProps<T>): import("@emotion/react/jsx-runtime").JSX.Element;
90
+ //#endregion
91
+ export { TagPicker };
@@ -0,0 +1,105 @@
1
+ import { Button } from "../Button/Button.js";
2
+ import { InlineMessage } from "../InlineMessage/InlineMessage.js";
3
+ import { offlineSectionStyles, tagPickerStyles } from "./styles.js";
4
+ import { TagTable } from "./TagTable.js";
5
+ import { TagSearchWithFilters } from "./TagSearchWithFilters.js";
6
+ import { css } from "@emotion/react";
7
+ import { Fragment, jsx, jsxs } from "@emotion/react/jsx-runtime";
8
+ //#region src/components/TagPicker/TagPicker.tsx
9
+ /**
10
+ * ## TagPicker
11
+ *
12
+ * *Status: Testing*
13
+ *
14
+ * **Peer dependencies:**
15
+ * - `react-aria-components`
16
+ *
17
+ * See the `peerDependencies` section of the `package.json` for compatible versions to install.
18
+ *
19
+ *
20
+ * #### Props
21
+ *
22
+ * See {@link TagPickerProps} for a full list of props and descriptions.
23
+ *
24
+ * #### Example
25
+ *
26
+ * This is currently still in testing phase, so a production implementation is not yet available.
27
+ */
28
+ function TagPicker({ addTag, loading, offline = false, onReorder, onSearch, options, proposedTags, readOnly = false, removeTag, retryConnection, tags, canRemove, filterRows, filterOptions, offlineBackupTags, highlightLeadingTag, searchPlaceholder = "Search for tags", searchLabel = "Search for tags", removeIcon, searchIcon, showTagType, showTagSectionName, theme, tagTableTheme, proposedTagTableTheme, autoCompleteTheme, selectTheme, cssOverrides }) {
29
+ const selectedTagIds = tags.map(({ id }) => id);
30
+ const proposedTagsWithoutSelected = proposedTags.filter(({ id }) => !selectedTagIds.includes(id));
31
+ const backupTagsWithoutSelected = offlineBackupTags?.filter(({ id }) => !selectedTagIds.includes(id)) ?? [];
32
+ const showBackupListWhenOffline = !readOnly && offlineBackupTags && backupTagsWithoutSelected.length > 0;
33
+ const optionsWithoutSelected = options.filter(({ id }) => !selectedTagIds.includes(id));
34
+ return /* @__PURE__ */ jsxs("div", {
35
+ css: [tagPickerStyles(theme), cssOverrides],
36
+ children: [
37
+ /* @__PURE__ */ jsx(TagSearchWithFilters, {
38
+ icon: searchIcon,
39
+ onSearch,
40
+ addSelection: addTag,
41
+ options: optionsWithoutSelected,
42
+ loading,
43
+ filterOptions,
44
+ disabled: readOnly || offline,
45
+ label: searchLabel,
46
+ placeholder: searchPlaceholder,
47
+ "data-testid": "tag-picker-search-input",
48
+ symbol: "search",
49
+ theme,
50
+ autoCompleteTheme,
51
+ selectTheme
52
+ }),
53
+ offline && /* @__PURE__ */ jsxs("div", {
54
+ css: offlineSectionStyles(theme),
55
+ children: [/* @__PURE__ */ jsxs(InlineMessage, {
56
+ level: "error",
57
+ children: [
58
+ "Unfortunately, we can't fetch tag information.",
59
+ " ",
60
+ showBackupListWhenOffline && "Choose from the following tags",
61
+ showBackupListWhenOffline && retryConnection && /* @__PURE__ */ jsx(Fragment, { children: " or " }),
62
+ retryConnection && /* @__PURE__ */ jsx(Button, {
63
+ size: "xs",
64
+ variant: "secondary",
65
+ onClick: () => retryConnection(),
66
+ children: "Retry"
67
+ })
68
+ ]
69
+ }), showBackupListWhenOffline && /* @__PURE__ */ jsx(Fragment, { children: backupTagsWithoutSelected.map((tag, index) => /* @__PURE__ */ jsx(Button, {
70
+ onClick: () => addTag(tag),
71
+ variant: "tertiary",
72
+ size: "sm",
73
+ cssOverrides: css({ justifyContent: theme?.offlineSection?.justifyContent ?? "flex-start" }),
74
+ "aria-label": `Add ${tag.name}`,
75
+ children: tag.name
76
+ }, index)) })]
77
+ }),
78
+ /* @__PURE__ */ jsx(TagTable, {
79
+ rows: tags,
80
+ canRemove,
81
+ removeAction: readOnly ? void 0 : removeTag,
82
+ filterRows,
83
+ onReorder: readOnly ? void 0 : onReorder,
84
+ "data-testid": "selected-tags-table",
85
+ highlightFirstRow: highlightLeadingTag,
86
+ showTagType,
87
+ showTagSectionName,
88
+ removeIcon,
89
+ theme: tagTableTheme
90
+ }),
91
+ !readOnly && /* @__PURE__ */ jsx(TagTable, {
92
+ heading: "Proposed Tags",
93
+ theme: proposedTagTableTheme,
94
+ filterRows,
95
+ showTagType,
96
+ showTagSectionName,
97
+ rows: proposedTagsWithoutSelected,
98
+ addAction: addTag,
99
+ "data-testid": "proposed-tags-table"
100
+ })
101
+ ]
102
+ });
103
+ }
104
+ //#endregion
105
+ export { TagPicker };
@@ -0,0 +1,53 @@
1
+ const require_Select = require("../Select/Select.cjs");
2
+ const require_styles = require("./styles.cjs");
3
+ const require_Autocomplete = require("./Autocomplete.cjs");
4
+ let react = require("react");
5
+ let _emotion_react = require("@emotion/react");
6
+ let _emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
7
+ //#region src/components/TagPicker/TagSearchWithFilters.tsx
8
+ function TagSearchWithFilters({ addSelection, onSearch, filterOptions, disabled, theme, autoCompleteTheme, selectTheme = {}, ...tagAutocompleteProps }) {
9
+ const [queryText, setQueryText] = (0, react.useState)("");
10
+ const [filterValue, setFilterValue] = (0, react.useState)(filterOptions?.[0]?.filter);
11
+ const onSearchRef = (0, react.useRef)(onSearch);
12
+ (0, react.useEffect)(() => {
13
+ onSearchRef.current = onSearch;
14
+ }, [onSearch]);
15
+ (0, react.useEffect)(() => {
16
+ if (queryText && queryText.length > 0) onSearchRef.current(queryText, filterValue && filterValue.length > 0 ? filterValue : void 0);
17
+ }, [filterValue, queryText]);
18
+ const shouldRenderSelect = filterOptions && filterOptions.length > 1;
19
+ return /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsxs)("div", {
20
+ css: require_styles.tagSearchWithFilterStyles(theme),
21
+ children: [/* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(require_Autocomplete.Autocomplete, {
22
+ cssOverrides: (0, _emotion_react.css)({ flex: 1 }),
23
+ onTextInputChange: setQueryText,
24
+ addSelection: (tag) => {
25
+ addSelection(tag);
26
+ setQueryText("");
27
+ },
28
+ value: queryText,
29
+ ...tagAutocompleteProps,
30
+ disabled,
31
+ theme: autoCompleteTheme,
32
+ addFirstOnEnter: true
33
+ }), shouldRenderSelect && /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(require_Select.Select, {
34
+ theme: require_styles.modifyFilterSelectTheme(selectTheme),
35
+ cssOverrides: require_styles.filterSelectCssOverrides(theme),
36
+ isDisabled: disabled,
37
+ value: filterValue,
38
+ placement: "bottom right",
39
+ shouldFlip: false,
40
+ onChange: (selection) => {
41
+ if (Array.isArray(selection) || selection === null) return;
42
+ setFilterValue(selection.toString());
43
+ },
44
+ children: filterOptions.map((data, index) => /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(require_Select.Option, {
45
+ value: data,
46
+ id: data.filter,
47
+ children: data.label
48
+ }, index))
49
+ })]
50
+ });
51
+ }
52
+ //#endregion
53
+ exports.TagSearchWithFilters = TagSearchWithFilters;
@@ -0,0 +1,53 @@
1
+ import { Option, Select } from "../Select/Select.js";
2
+ import { filterSelectCssOverrides, modifyFilterSelectTheme, tagSearchWithFilterStyles } from "./styles.js";
3
+ import { Autocomplete } from "./Autocomplete.js";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { css } from "@emotion/react";
6
+ import { jsx, jsxs } from "@emotion/react/jsx-runtime";
7
+ //#region src/components/TagPicker/TagSearchWithFilters.tsx
8
+ function TagSearchWithFilters({ addSelection, onSearch, filterOptions, disabled, theme, autoCompleteTheme, selectTheme = {}, ...tagAutocompleteProps }) {
9
+ const [queryText, setQueryText] = useState("");
10
+ const [filterValue, setFilterValue] = useState(filterOptions?.[0]?.filter);
11
+ const onSearchRef = useRef(onSearch);
12
+ useEffect(() => {
13
+ onSearchRef.current = onSearch;
14
+ }, [onSearch]);
15
+ useEffect(() => {
16
+ if (queryText && queryText.length > 0) onSearchRef.current(queryText, filterValue && filterValue.length > 0 ? filterValue : void 0);
17
+ }, [filterValue, queryText]);
18
+ const shouldRenderSelect = filterOptions && filterOptions.length > 1;
19
+ return /* @__PURE__ */ jsxs("div", {
20
+ css: tagSearchWithFilterStyles(theme),
21
+ children: [/* @__PURE__ */ jsx(Autocomplete, {
22
+ cssOverrides: css({ flex: 1 }),
23
+ onTextInputChange: setQueryText,
24
+ addSelection: (tag) => {
25
+ addSelection(tag);
26
+ setQueryText("");
27
+ },
28
+ value: queryText,
29
+ ...tagAutocompleteProps,
30
+ disabled,
31
+ theme: autoCompleteTheme,
32
+ addFirstOnEnter: true
33
+ }), shouldRenderSelect && /* @__PURE__ */ jsx(Select, {
34
+ theme: modifyFilterSelectTheme(selectTheme),
35
+ cssOverrides: filterSelectCssOverrides(theme),
36
+ isDisabled: disabled,
37
+ value: filterValue,
38
+ placement: "bottom right",
39
+ shouldFlip: false,
40
+ onChange: (selection) => {
41
+ if (Array.isArray(selection) || selection === null) return;
42
+ setFilterValue(selection.toString());
43
+ },
44
+ children: filterOptions.map((data, index) => /* @__PURE__ */ jsx(Option, {
45
+ value: data,
46
+ id: data.filter,
47
+ children: data.label
48
+ }, index))
49
+ })]
50
+ });
51
+ }
52
+ //#endregion
53
+ export { TagSearchWithFilters };
@@ -28,37 +28,13 @@ const defaultCanRemove = () => true;
28
28
  *
29
29
  * ## Usage
30
30
  *
31
- * *Example with TagAutocomplete and TagTable combined:*
31
+ * *Example with TagTable:*
32
32
  *
33
33
  * ```tsx
34
- * import { TagAutocomplete, TagTable } from '@guardian/stand';
34
+ * import { TagTable } from '@guardian/stand';
35
35
  *
36
- * const Component = () => {
37
- * const [selectedTags, setSelectedTags] = useState<
38
- * TagManagerObjectData[] // TagManagerObjectData is an internal type representing a Tag
39
- * >([]);
40
-
41
- * const [options, setOptions] = useState<TagManagerObjectData[]>([]);
42
- * const [value, setValue] = useState('');
43
- * const onChange = (inputText: string) => {
44
- * setValue(inputText);
45
- * if (inputText === '') {
46
- * setOptions([]);
47
- * return;
48
- * }
49
- *
50
- * if (inputText === '*') {
51
- * setOptions(exampleTags); // exampleTags is an array of Tags
52
- * return;
53
- * }
54
- *
55
- * // Simple filtering against exampleTags
56
- * const filteredItems = exampleTags.filter((t) =>
57
- * t.internalName.toLowerCase().includes(inputText.toLowerCase()),
58
- * );
59
- * return setOptions(filteredItems);
60
- * };
61
-
36
+ * // TagManagerObjectData is an internal type representing a Tag
37
+ * const Component = ({selectedTags}:{selectedTags:TagManagerObjectData[]}) => {
62
38
  * return (
63
39
  * <>
64
40
  * <div
@@ -66,25 +42,10 @@ const defaultCanRemove = () => true;
66
42
  * display: flex;
67
43
  * `}
68
44
  * >
69
- * <TagAutocomplete
70
- * onChange={onChange}
71
- * options={options}
72
- * label="Tags"
73
- * addTag={(tag) =>
74
- * setSelectedTags((tags) => {
75
- * return [...tags, tag];
76
- * })
77
- * }
78
- * loading={false}
79
- * placeholder={''}
80
- * disabled={false}
81
- * value={value}
82
- * />
83
- * <select>
84
- * option>All tags</option>
85
- * </select>
86
- * </div>
87
45
  * <TagTable rows={selectedTags} filterRows={() => true} />
46
+ * <div>
47
+ * there are {selectedTags.length} tags.
48
+ * </div>
88
49
  * </>
89
50
  * );
90
51
  * };
@@ -98,7 +59,7 @@ const defaultCanRemove = () => true;
98
59
  *
99
60
  * This is currently still in testing phase, so a production implementation is not yet available.
100
61
  */
101
- function TagTable({ rows, filterRows, heading, showTagType, showTagSectionName, removeAction: removeTag, addAction: addTag, onReorder, canRemove = defaultCanRemove, "data-testid": dataTestId, removeIcon, gripIcon, theme, cssOverrides }) {
62
+ function TagTable({ rows, filterRows, heading, showTagType, showTagSectionName, highlightFirstRow = false, removeAction: removeTag, addAction: addTag, onReorder, canRemove = defaultCanRemove, "data-testid": dataTestId, removeIcon, gripIcon, theme, cssOverrides }) {
102
63
  const canDrag = !!onReorder;
103
64
  const [localRows, setLocalRows] = (0, react.useState)(() => [...rows]);
104
65
  const localRowsRef = (0, react.useRef)(localRows);
@@ -106,7 +67,7 @@ function TagTable({ rows, filterRows, heading, showTagType, showTagSectionName,
106
67
  (0, react.useEffect)(() => {
107
68
  setLocalRows([...rows]);
108
69
  }, [rows]);
109
- const filtered = localRows.filter(filterRows);
70
+ const filtered = filterRows ? localRows.filter(filterRows) : [...localRows];
110
71
  const { dragAndDropHooks } = (0, react_aria_components.useDragAndDrop)({
111
72
  getItems: (_keys, items) => {
112
73
  return items.map((item) => ({ "text/plain": rowToTag(item).id.toString() }));
@@ -155,7 +116,7 @@ function TagTable({ rows, filterRows, heading, showTagType, showTagSectionName,
155
116
  dependencies: [localRows],
156
117
  children: (item) => /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsxs)(react_aria_components.Row, {
157
118
  id: rowToTag(item).id,
158
- css: require_styles.tagTableRowStyles(canDrag, theme),
119
+ css: require_styles.tagTableRowStyles(canDrag, highlightFirstRow, theme),
159
120
  textValue: rowToTag(item).name,
160
121
  children: [
161
122
  onReorder && /* @__PURE__ */ (0, _emotion_react_jsx_runtime.jsx)(react_aria_components.Cell, {
@@ -1,6 +1,6 @@
1
1
  import { DeepPartial } from "../../util/types.cjs";
2
- import { TagRow } from "./types.cjs";
3
2
  import { ComponentTagTable } from "../../styleD/build/typescript/component/tagTable.cjs";
3
+ import { TagRow } from "./types.cjs";
4
4
  import { SerializedStyles } from "@emotion/react";
5
5
  import { ReactElement } from "react";
6
6
 
@@ -12,7 +12,7 @@ interface TagTableProps<R extends Row> {
12
12
  /** `rows` - The collection of rows */
13
13
  rows: R[];
14
14
  /** `filterRows` - Function to filter rows from `rows` prop from appearing in the table */
15
- filterRows: (row: R) => boolean;
15
+ filterRows?: (row: R) => boolean;
16
16
  /** `heading` - The table heading */
17
17
  heading?: string;
18
18
  /** `showTagType` - Whether to show tags' type in table */
@@ -21,6 +21,8 @@ interface TagTableProps<R extends Row> {
21
21
  showTagSectionName?: boolean;
22
22
  /** `removeAction` - Function called when the Remove button is pressed on a row */
23
23
  removeAction?: (tag: R) => void;
24
+ /** `highlightFirstRow` - Whether to highlight the first row ("leading tag") */
25
+ highlightFirstRow?: boolean;
24
26
  /** `addAction` - Function called when the Add button is pressed on a row */
25
27
  addAction?: (tag: R) => void;
26
28
  /** `onReorder` - Function called when a re-ordering of rows through drag and drop is performed */
@@ -53,37 +55,13 @@ interface TagTableProps<R extends Row> {
53
55
  *
54
56
  * ## Usage
55
57
  *
56
- * *Example with TagAutocomplete and TagTable combined:*
58
+ * *Example with TagTable:*
57
59
  *
58
60
  * ```tsx
59
- * import { TagAutocomplete, TagTable } from '@guardian/stand';
60
- *
61
- * const Component = () => {
62
- * const [selectedTags, setSelectedTags] = useState<
63
- * TagManagerObjectData[] // TagManagerObjectData is an internal type representing a Tag
64
- * >([]);
65
-
66
- * const [options, setOptions] = useState<TagManagerObjectData[]>([]);
67
- * const [value, setValue] = useState('');
68
- * const onChange = (inputText: string) => {
69
- * setValue(inputText);
70
- * if (inputText === '') {
71
- * setOptions([]);
72
- * return;
73
- * }
74
- *
75
- * if (inputText === '*') {
76
- * setOptions(exampleTags); // exampleTags is an array of Tags
77
- * return;
78
- * }
61
+ * import { TagTable } from '@guardian/stand';
79
62
  *
80
- * // Simple filtering against exampleTags
81
- * const filteredItems = exampleTags.filter((t) =>
82
- * t.internalName.toLowerCase().includes(inputText.toLowerCase()),
83
- * );
84
- * return setOptions(filteredItems);
85
- * };
86
-
63
+ * // TagManagerObjectData is an internal type representing a Tag
64
+ * const Component = ({selectedTags}:{selectedTags:TagManagerObjectData[]}) => {
87
65
  * return (
88
66
  * <>
89
67
  * <div
@@ -91,25 +69,10 @@ interface TagTableProps<R extends Row> {
91
69
  * display: flex;
92
70
  * `}
93
71
  * >
94
- * <TagAutocomplete
95
- * onChange={onChange}
96
- * options={options}
97
- * label="Tags"
98
- * addTag={(tag) =>
99
- * setSelectedTags((tags) => {
100
- * return [...tags, tag];
101
- * })
102
- * }
103
- * loading={false}
104
- * placeholder={''}
105
- * disabled={false}
106
- * value={value}
107
- * />
108
- * <select>
109
- * option>All tags</option>
110
- * </select>
111
- * </div>
112
72
  * <TagTable rows={selectedTags} filterRows={() => true} />
73
+ * <div>
74
+ * there are {selectedTags.length} tags.
75
+ * </div>
113
76
  * </>
114
77
  * );
115
78
  * };
@@ -129,6 +92,7 @@ declare function TagTable<R extends Row>({
129
92
  heading,
130
93
  showTagType,
131
94
  showTagSectionName,
95
+ highlightFirstRow,
132
96
  removeAction: removeTag,
133
97
  addAction: addTag,
134
98
  onReorder,