@bitrise/bitkit-v2 0.3.481-beta.3079 → 0.3.481-beta.3083

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 (143) hide show
  1. package/dist/components/BitkitCalendar/BitkitCalendar.d.ts +0 -12
  2. package/dist/components/BitkitCalendar/BitkitCalendar.js +1 -7
  3. package/dist/components/BitkitCalendar/BitkitCalendar.js.map +1 -1
  4. package/dist/components/BitkitCalendar/components/CalendarContent.d.ts +1 -5
  5. package/dist/components/BitkitCalendar/components/CalendarContent.js +43 -60
  6. package/dist/components/BitkitCalendar/components/CalendarContent.js.map +1 -1
  7. package/dist/components/BitkitCalendar/components/CalendarMonth.d.ts +2 -4
  8. package/dist/components/BitkitCalendar/components/CalendarMonth.js +5 -15
  9. package/dist/components/BitkitCalendar/components/CalendarMonth.js.map +1 -1
  10. package/dist/components/BitkitCalendar/components/CalendarMonthSelect.d.ts +1 -2
  11. package/dist/components/BitkitCalendar/components/CalendarMonthSelect.js +2 -3
  12. package/dist/components/BitkitCalendar/components/CalendarMonthSelect.js.map +1 -1
  13. package/dist/components/BitkitCalendar/components/CalendarNextTrigger.d.ts +1 -3
  14. package/dist/components/BitkitCalendar/components/CalendarNextTrigger.js +3 -3
  15. package/dist/components/BitkitCalendar/components/CalendarNextTrigger.js.map +1 -1
  16. package/dist/components/BitkitCalendar/components/CalendarPrevTrigger.d.ts +1 -3
  17. package/dist/components/BitkitCalendar/components/CalendarPrevTrigger.js +3 -3
  18. package/dist/components/BitkitCalendar/components/CalendarPrevTrigger.js.map +1 -1
  19. package/dist/components/BitkitCalendar/components/CalendarSelect.d.ts +0 -1
  20. package/dist/components/BitkitCalendar/components/CalendarSelect.js +3 -5
  21. package/dist/components/BitkitCalendar/components/CalendarSelect.js.map +1 -1
  22. package/dist/components/BitkitCalendar/components/CalendarTrigger.js +0 -1
  23. package/dist/components/BitkitCalendar/components/CalendarTrigger.js.map +1 -1
  24. package/dist/components/BitkitCalendar/components/CalendarYearSelect.d.ts +1 -2
  25. package/dist/components/BitkitCalendar/components/CalendarYearSelect.js +2 -3
  26. package/dist/components/BitkitCalendar/components/CalendarYearSelect.js.map +1 -1
  27. package/dist/components/BitkitDatePicker/BitkitDatePicker.d.ts +0 -2
  28. package/dist/components/BitkitDatePicker/BitkitDatePicker.js +1 -2
  29. package/dist/components/BitkitDatePicker/BitkitDatePicker.js.map +1 -1
  30. package/dist/components/BitkitLabelTooltip/BitkitLabelTooltip.d.ts +3 -4
  31. package/dist/components/BitkitLabelTooltip/BitkitLabelTooltip.js +2 -3
  32. package/dist/components/BitkitLabelTooltip/BitkitLabelTooltip.js.map +1 -1
  33. package/dist/components/BitkitMarkdown/BitkitMarkdown.js +1 -1
  34. package/dist/components/BitkitNoteCard/BitkitNoteCard.js +1 -1
  35. package/dist/components/BitkitPageSidebar/BitkitPageSidebar.js +1 -1
  36. package/dist/components/BitkitUIHeader/BitkitUIHeader.d.ts +37 -0
  37. package/dist/components/BitkitUIHeader/BitkitUIHeader.js +113 -0
  38. package/dist/components/BitkitUIHeader/BitkitUIHeader.js.map +1 -0
  39. package/dist/components/BitkitUIHeader/BitriseLogo.d.ts +10 -0
  40. package/dist/components/BitkitUIHeader/BitriseLogo.js +86 -0
  41. package/dist/components/BitkitUIHeader/BitriseLogo.js.map +1 -0
  42. package/dist/components/BitkitUIHeader/UIHeaderAccount.d.ts +26 -0
  43. package/dist/components/BitkitUIHeader/UIHeaderAccount.js +40 -0
  44. package/dist/components/BitkitUIHeader/UIHeaderAccount.js.map +1 -0
  45. package/dist/components/BitkitUIHeader/UIHeaderButton.d.ts +34 -0
  46. package/dist/components/BitkitUIHeader/UIHeaderButton.js +43 -0
  47. package/dist/components/BitkitUIHeader/UIHeaderButton.js.map +1 -0
  48. package/dist/components/BitkitUIHeader/UIHeaderContext.d.ts +13 -0
  49. package/dist/components/BitkitUIHeader/UIHeaderContext.js +11 -0
  50. package/dist/components/BitkitUIHeader/UIHeaderContext.js.map +1 -0
  51. package/dist/components/BitkitUIHeader/UIHeaderControl.d.ts +65 -0
  52. package/dist/components/BitkitUIHeader/UIHeaderControl.js +72 -0
  53. package/dist/components/BitkitUIHeader/UIHeaderControl.js.map +1 -0
  54. package/dist/components/BitkitUIHeader/UIHeaderNavButton.d.ts +20 -0
  55. package/dist/components/BitkitUIHeader/UIHeaderNavButton.js +46 -0
  56. package/dist/components/BitkitUIHeader/UIHeaderNavButton.js.map +1 -0
  57. package/dist/components/BitkitUIHeader/UIHeaderSearch.d.ts +32 -0
  58. package/dist/components/BitkitUIHeader/UIHeaderSearch.js +116 -0
  59. package/dist/components/BitkitUIHeader/UIHeaderSearch.js.map +1 -0
  60. package/dist/components/BitkitUIHeader/uiHeaderPart.d.ts +9 -0
  61. package/dist/components/BitkitUIHeader/uiHeaderPart.js +13 -0
  62. package/dist/components/BitkitUIHeader/uiHeaderPart.js.map +1 -0
  63. package/dist/components/index.d.ts +1 -6
  64. package/dist/main.js +9 -8
  65. package/dist/theme/recipes/UIHeaderButton.recipe.js +103 -0
  66. package/dist/theme/recipes/UIHeaderButton.recipe.js.map +1 -0
  67. package/dist/theme/recipes/index.js +3 -1
  68. package/dist/theme/recipes/index.js.map +1 -1
  69. package/dist/theme/semantic-tokens/index.d.ts +5 -0
  70. package/dist/theme/semantic-tokens/semanticColors.d.ts +5 -0
  71. package/dist/theme/semantic-tokens/semanticColors.js +1 -0
  72. package/dist/theme/semantic-tokens/semanticColors.js.map +1 -1
  73. package/dist/theme/slot-recipes/DatePicker.recipe.d.ts +0 -15
  74. package/dist/theme/slot-recipes/DatePicker.recipe.js +22 -72
  75. package/dist/theme/slot-recipes/DatePicker.recipe.js.map +1 -1
  76. package/dist/theme/slot-recipes/DatePickerSelect.recipe.d.ts +0 -85
  77. package/dist/theme/slot-recipes/DatePickerSelect.recipe.js +10 -35
  78. package/dist/theme/slot-recipes/DatePickerSelect.recipe.js.map +1 -1
  79. package/dist/theme/slot-recipes/Menu.recipe.js +1 -6
  80. package/dist/theme/slot-recipes/Menu.recipe.js.map +1 -1
  81. package/dist/theme/slot-recipes/Tag.recipe.d.ts +1 -1
  82. package/dist/theme/slot-recipes/UIHeader.recipe.d.ts +4 -0
  83. package/dist/theme/slot-recipes/UIHeader.recipe.js +243 -0
  84. package/dist/theme/slot-recipes/UIHeader.recipe.js.map +1 -0
  85. package/dist/theme/slot-recipes/UISideNav.recipe.d.ts +1 -2
  86. package/dist/theme/slot-recipes/UISideNav.recipe.js +2 -3
  87. package/dist/theme/slot-recipes/UISideNav.recipe.js.map +1 -1
  88. package/dist/theme/slot-recipes/index.d.ts +3 -160
  89. package/dist/theme/slot-recipes/index.js +2 -4
  90. package/dist/theme/slot-recipes/index.js.map +1 -1
  91. package/dist/theme/themeUtils.d.ts +6 -0
  92. package/dist/theme/themeUtils.js +7 -1
  93. package/dist/theme/themeUtils.js.map +1 -1
  94. package/dist/utilities/BitkitPortalContext.js +2 -3
  95. package/dist/utilities/BitkitPortalContext.js.map +1 -1
  96. package/docs/v1-to-v2-migration-guide.md +1 -48
  97. package/package.json +1 -1
  98. package/dist/components/BitkitFilter/BitkitFilter.context.d.ts +0 -65
  99. package/dist/components/BitkitFilter/BitkitFilter.context.js +0 -82
  100. package/dist/components/BitkitFilter/BitkitFilter.context.js.map +0 -1
  101. package/dist/components/BitkitFilter/BitkitFilter.d.ts +0 -55
  102. package/dist/components/BitkitFilter/BitkitFilter.js +0 -247
  103. package/dist/components/BitkitFilter/BitkitFilter.js.map +0 -1
  104. package/dist/components/BitkitFilter/BitkitFilter.utils.d.ts +0 -18
  105. package/dist/components/BitkitFilter/BitkitFilter.utils.js +0 -42
  106. package/dist/components/BitkitFilter/BitkitFilter.utils.js.map +0 -1
  107. package/dist/components/BitkitFilter/BitkitFilterAdd.d.ts +0 -18
  108. package/dist/components/BitkitFilter/BitkitFilterAdd.js +0 -200
  109. package/dist/components/BitkitFilter/BitkitFilterAdd.js.map +0 -1
  110. package/dist/components/BitkitFilter/BitkitFilterDateRange.d.ts +0 -26
  111. package/dist/components/BitkitFilter/BitkitFilterDateRange.js +0 -118
  112. package/dist/components/BitkitFilter/BitkitFilterDateRange.js.map +0 -1
  113. package/dist/components/BitkitFilter/BitkitFilterSearch.d.ts +0 -23
  114. package/dist/components/BitkitFilter/BitkitFilterSearch.js +0 -72
  115. package/dist/components/BitkitFilter/BitkitFilterSearch.js.map +0 -1
  116. package/dist/components/BitkitFilter/BitkitFilterSelect.d.ts +0 -61
  117. package/dist/components/BitkitFilter/BitkitFilterSelect.js +0 -149
  118. package/dist/components/BitkitFilter/BitkitFilterSelect.js.map +0 -1
  119. package/dist/components/BitkitFilter/BitkitFilterSwitch.d.ts +0 -28
  120. package/dist/components/BitkitFilter/BitkitFilterSwitch.js +0 -87
  121. package/dist/components/BitkitFilter/BitkitFilterSwitch.js.map +0 -1
  122. package/dist/components/BitkitFilter/components/FilterChip.d.ts +0 -23
  123. package/dist/components/BitkitFilter/components/FilterChip.js +0 -66
  124. package/dist/components/BitkitFilter/components/FilterChip.js.map +0 -1
  125. package/dist/components/BitkitFilter/components/FilterField.d.ts +0 -15
  126. package/dist/components/BitkitFilter/components/FilterField.js +0 -60
  127. package/dist/components/BitkitFilter/components/FilterField.js.map +0 -1
  128. package/dist/components/BitkitFilter/components/FilterPanel.d.ts +0 -42
  129. package/dist/components/BitkitFilter/components/FilterPanel.js +0 -126
  130. package/dist/components/BitkitFilter/components/FilterPanel.js.map +0 -1
  131. package/dist/components/BitkitFilter/components/FilterSearchInput.d.ts +0 -15
  132. package/dist/components/BitkitFilter/components/FilterSearchInput.js +0 -42
  133. package/dist/components/BitkitFilter/components/FilterSearchInput.js.map +0 -1
  134. package/dist/components/BitkitFilter/components/FilterSelectForm.d.ts +0 -45
  135. package/dist/components/BitkitFilter/components/FilterSelectForm.js +0 -341
  136. package/dist/components/BitkitFilter/components/FilterSelectForm.js.map +0 -1
  137. package/dist/theme/recipes/index.d.ts +0 -525
  138. package/dist/theme/slot-recipes/Filter.recipe.d.ts +0 -37
  139. package/dist/theme/slot-recipes/Filter.recipe.js +0 -655
  140. package/dist/theme/slot-recipes/Filter.recipe.js.map +0 -1
  141. package/dist/theme/slot-recipes/Listbox.recipe.d.ts +0 -22
  142. package/dist/theme/slot-recipes/Listbox.recipe.js +0 -96
  143. package/dist/theme/slot-recipes/Listbox.recipe.js.map +0 -1
@@ -1,61 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- import { BitkitFilterSelectItem } from './components/FilterSelectForm';
3
- export type { BitkitFilterSelectItem };
4
- export interface BitkitFilterSelectProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {
5
- /**
6
- * Why the filter doesn't apply yet, e.g. "Select a project first". Its entry in the "Add filter"
7
- * menu is muted with an info icon, and says this in a tooltip when highlighted (spelled out under
8
- * the label on mobile). Only applies inside `BitkitFilter.Add`. A filter with no options is
9
- * disabled anyway.
10
- */
11
- disabledReason?: string;
12
- /** Chip text while nothing is selected. Defaults to `All {pluralLabel}`. */
13
- emptyLabel?: string;
14
- items: BitkitFilterSelectItem[];
15
- /** Name of the filter: the popover title, and the prefix of a single selection on the chip (`Project: iOS`). */
16
- label: string;
17
- /** Shows a loading row in place of the options, e.g. while `onSearchChange` results are fetched. */
18
- loading?: boolean;
19
- /** Text of the loading row. Defaults to "Loading...". */
20
- loadingLabel?: string;
21
- multiple?: boolean;
22
- /**
23
- * Hands search over to you: `items` are shown as they are, without filtering them locally. Use it
24
- * for server-side search. Called once typing pauses (300ms), right away with `''` on clear and
25
- * close; ordering the responses is up to you. The search input is always shown with it; otherwise
26
- * only above 5 items.
27
- */
28
- onSearchChange?: (searchText: string) => void;
29
- /** Called on "Apply", "Clear" and the chip's remove button — not on every click in the popover. */
30
- onValueChange: (value: string[]) => void;
31
- /**
32
- * Offers a wildcard pattern (`release-*`) as an alternative to picking options. A pattern is
33
- * applied as the single value, e.g. `['release-*']`; matching it is up to you. The preview of
34
- * matching options only checks the labels of the `items` at hand, not a server search.
35
- */
36
- pattern?: boolean;
37
- /**
38
- * Plural of `label`: the empty chip (`All projects`), a multiple selection (`2 workflows`), and a
39
- * multi-select's panel title. Required, since a guessed plural reads wrong too often.
40
- */
41
- pluralLabel: string;
42
- /** Lists the options in the order of `items`, instead of the applied ones first. */
43
- preserveOrder?: boolean;
44
- /**
45
- * A value is always applied, so the popover offers no "Clear". Pass the default as `resetValue`
46
- * too, for "Clear filters" to restore. Not for a filter inside `BitkitFilter.Add`.
47
- */
48
- required?: boolean;
49
- /** The value "Clear filters" restores. Defaults to no selection. */
50
- resetValue?: string[];
51
- /** Defaults to "Search for options". */
52
- searchPlaceholder?: string;
53
- value: string[];
54
- }
55
- /**
56
- * A filter picking one or more options from a list, applied with the popover's "Apply". Directly
57
- * in `BitkitFilter` it is a dropdown chip that is always shown; inside `BitkitFilter.Add` it is a
58
- * removable chip that only appears while it holds a value.
59
- */
60
- declare const BitkitFilterSelect: import('react').ForwardRefExoticComponent<BitkitFilterSelectProps & import('react').RefAttributes<HTMLButtonElement>>;
61
- export default BitkitFilterSelect;
@@ -1,149 +0,0 @@
1
- import { isPattern, toRunningText } from "./BitkitFilter.utils.js";
2
- import { useFilterAddItem, useFilterContext, useFilterRegistration } from "./BitkitFilter.context.js";
3
- import FilterChip from "./components/FilterChip.js";
4
- import FilterField from "./components/FilterField.js";
5
- import FilterPanel from "./components/FilterPanel.js";
6
- import FilterSelectForm from "./components/FilterSelectForm.js";
7
- import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
8
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
- import { mergeRefs } from "@chakra-ui/react";
10
- //#region lib/components/BitkitFilter/BitkitFilterSelect.tsx
11
- var NO_VALUE = [];
12
- /**
13
- * A filter picking one or more options from a list, applied with the popover's "Apply". Directly
14
- * in `BitkitFilter` it is a dropdown chip that is always shown; inside `BitkitFilter.Add` it is a
15
- * removable chip that only appears while it holds a value.
16
- */
17
- var BitkitFilterSelect = forwardRef((props, ref) => {
18
- const { disabledReason, emptyLabel, items, label, loading, loadingLabel, multiple, onSearchChange, onValueChange, pattern, pluralLabel, preserveOrder, required, resetValue = NO_VALUE, searchPlaceholder, value, ...rest } = props;
19
- const { isMobile } = useFilterContext();
20
- const [open, setOpen] = useState(false);
21
- const addItem = useFilterAddItem({
22
- disabledReason,
23
- hasOptions: !!items.length || !!onSearchChange,
24
- isEmpty: !value.length,
25
- label
26
- });
27
- useFilterRegistration(value, resetValue, onValueChange);
28
- const knownItems = useRef(/* @__PURE__ */ new Map());
29
- items.forEach((item) => knownItems.current.set(item.value, item));
30
- const triggerRef = useRef(null);
31
- const setRef = useMemo(() => mergeRefs(ref, triggerRef), [ref]);
32
- const isFocusPending = useRef(false);
33
- const isEmptiedFromChip = useRef(false);
34
- const searchTimeout = useRef(void 0);
35
- useEffect(() => () => clearTimeout(searchTimeout.current), []);
36
- const search = (text) => {
37
- clearTimeout(searchTimeout.current);
38
- if (text) searchTimeout.current = setTimeout(() => onSearchChange?.(text), 300);
39
- else onSearchChange?.("");
40
- };
41
- const onOpenChange = (isOpen) => {
42
- setOpen(isOpen);
43
- if (!isOpen && onSearchChange) search("");
44
- };
45
- const form = (isAdding) => /* @__PURE__ */ jsx(FilterSelectForm, {
46
- isEditing: !!value.length,
47
- isOrderFixed: preserveOrder,
48
- isRequired: required && !addItem,
49
- items,
50
- label,
51
- loading,
52
- loadingLabel,
53
- multiple,
54
- onApply: (next) => {
55
- if (isAdding) isFocusPending.current = true;
56
- onValueChange(next);
57
- if (isAdding) addItem?.stopAdding();
58
- else if (addItem && !next.length) isEmptiedFromChip.current = true;
59
- onOpenChange(false);
60
- },
61
- onCancel: () => {
62
- if (isAdding) addItem?.stopAdding();
63
- onOpenChange(false);
64
- },
65
- onSearchChange: onSearchChange ? search : void 0,
66
- pattern,
67
- pluralLabel,
68
- searchPlaceholder,
69
- selectedItems: value.filter((selected) => !isPattern(selected)).map((selected) => knownItems.current.get(selected) ?? {
70
- label: selected,
71
- value: selected
72
- }),
73
- value
74
- });
75
- const addPanel = addItem ? /* @__PURE__ */ jsx(FilterPanel, {
76
- finalFocusEl: () => {
77
- const chip = isFocusPending.current ? triggerRef.current : null;
78
- isFocusPending.current = false;
79
- return chip ?? addItem.getTrigger();
80
- },
81
- getAnchorElement: addItem.getTrigger,
82
- onOpenChange: (isOpen) => {
83
- if (isOpen) return;
84
- addItem.stopAdding();
85
- onOpenChange(false);
86
- },
87
- open: addItem.isAdding,
88
- children: form(true)
89
- }) : null;
90
- const emptyText = emptyLabel ?? `All ${toRunningText(pluralLabel)}`;
91
- const singleText = value.length === 1 ? knownItems.current.get(value[0])?.label ?? value[0] : "";
92
- const onRemove = addItem ? () => {
93
- onValueChange([]);
94
- addItem.focusTrigger();
95
- } : void 0;
96
- const hasChip = !addItem || !!value.length;
97
- let trigger = null;
98
- if (hasChip && isMobile) {
99
- let fieldValue = emptyText;
100
- if (value.length > 1) fieldValue = `${value.length} selected`;
101
- else if (value.length) fieldValue = singleText;
102
- trigger = /* @__PURE__ */ jsx(FilterField, {
103
- ...rest,
104
- isOpen: open,
105
- label: multiple ? pluralLabel : label,
106
- onClick: () => onOpenChange(true),
107
- onRemove,
108
- ref: setRef,
109
- value: fieldValue
110
- });
111
- } else if (hasChip) {
112
- let chipProps = { value: emptyText };
113
- if (value.length > 1) chipProps = {
114
- label: toRunningText(pluralLabel),
115
- labelAfter: true,
116
- value: value.length
117
- };
118
- else if (value.length) chipProps = {
119
- label: `${label}:`,
120
- value: singleText
121
- };
122
- trigger = /* @__PURE__ */ jsx(FilterChip, {
123
- ...chipProps,
124
- onRemove,
125
- ref: setRef,
126
- removeLabel: `Remove ${label} filter`,
127
- ...rest
128
- });
129
- }
130
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(FilterPanel, {
131
- finalFocusEl: addItem ? () => {
132
- if (!isEmptiedFromChip.current) return null;
133
- isEmptiedFromChip.current = false;
134
- const addTrigger = addItem.getTrigger();
135
- if (addTrigger instanceof HTMLButtonElement && !addTrigger.disabled) return addTrigger;
136
- addItem.focusTrigger();
137
- return null;
138
- } : void 0,
139
- onOpenChange,
140
- open,
141
- trigger,
142
- children: form(false)
143
- }), addPanel] });
144
- });
145
- BitkitFilterSelect.displayName = "BitkitFilterSelect";
146
- //#endregion
147
- export { BitkitFilterSelect as default };
148
-
149
- //# sourceMappingURL=BitkitFilterSelect.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BitkitFilterSelect.js","names":["_Fragment"],"sources":["../../../lib/components/BitkitFilter/BitkitFilterSelect.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { mergeRefs } from '@chakra-ui/react';\nimport { type BoxProps } from '@chakra-ui/react/box';\nimport { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useFilterAddItem, useFilterContext, useFilterRegistration } from './BitkitFilter.context';\nimport { isPattern, SEARCH_DEBOUNCE_MS, toRunningText } from './BitkitFilter.utils';\nimport FilterChip, { type FilterChipProps } from './components/FilterChip';\nimport FilterField from './components/FilterField';\nimport FilterPanel from './components/FilterPanel';\nimport FilterSelectForm, { type BitkitFilterSelectItem } from './components/FilterSelectForm';\n\nexport type { BitkitFilterSelectItem };\n\nconst NO_VALUE: string[] = [];\n\nexport interface BitkitFilterSelectProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {\n /**\n * Why the filter doesn't apply yet, e.g. \"Select a project first\". Its entry in the \"Add filter\"\n * menu is muted with an info icon, and says this in a tooltip when highlighted (spelled out under\n * the label on mobile). Only applies inside `BitkitFilter.Add`. A filter with no options is\n * disabled anyway.\n */\n disabledReason?: string;\n /** Chip text while nothing is selected. Defaults to `All {pluralLabel}`. */\n emptyLabel?: string;\n items: BitkitFilterSelectItem[];\n /** Name of the filter: the popover title, and the prefix of a single selection on the chip (`Project: iOS`). */\n label: string;\n /** Shows a loading row in place of the options, e.g. while `onSearchChange` results are fetched. */\n loading?: boolean;\n /** Text of the loading row. Defaults to \"Loading...\". */\n loadingLabel?: string;\n multiple?: boolean;\n /**\n * Hands search over to you: `items` are shown as they are, without filtering them locally. Use it\n * for server-side search. Called once typing pauses (300ms), right away with `''` on clear and\n * close; ordering the responses is up to you. The search input is always shown with it; otherwise\n * only above 5 items.\n */\n onSearchChange?: (searchText: string) => void;\n /** Called on \"Apply\", \"Clear\" and the chip's remove button — not on every click in the popover. */\n onValueChange: (value: string[]) => void;\n /**\n * Offers a wildcard pattern (`release-*`) as an alternative to picking options. A pattern is\n * applied as the single value, e.g. `['release-*']`; matching it is up to you. The preview of\n * matching options only checks the labels of the `items` at hand, not a server search.\n */\n pattern?: boolean;\n /**\n * Plural of `label`: the empty chip (`All projects`), a multiple selection (`2 workflows`), and a\n * multi-select's panel title. Required, since a guessed plural reads wrong too often.\n */\n pluralLabel: string;\n /** Lists the options in the order of `items`, instead of the applied ones first. */\n preserveOrder?: boolean;\n /**\n * A value is always applied, so the popover offers no \"Clear\". Pass the default as `resetValue`\n * too, for \"Clear filters\" to restore. Not for a filter inside `BitkitFilter.Add`.\n */\n required?: boolean;\n /** The value \"Clear filters\" restores. Defaults to no selection. */\n resetValue?: string[];\n /** Defaults to \"Search for options\". */\n searchPlaceholder?: string;\n value: string[];\n}\n\n/**\n * A filter picking one or more options from a list, applied with the popover's \"Apply\". Directly\n * in `BitkitFilter` it is a dropdown chip that is always shown; inside `BitkitFilter.Add` it is a\n * removable chip that only appears while it holds a value.\n */\n// The ref lands on the chip's (or on mobile the field's) button; other props on its wrapper.\nconst BitkitFilterSelect = forwardRef<HTMLButtonElement, BitkitFilterSelectProps>((props, ref) => {\n const {\n disabledReason,\n emptyLabel,\n items,\n label,\n loading,\n loadingLabel,\n multiple,\n onSearchChange,\n onValueChange,\n pattern,\n pluralLabel,\n preserveOrder,\n required,\n resetValue = NO_VALUE,\n searchPlaceholder,\n value,\n ...rest\n } = props;\n const { isMobile } = useFilterContext();\n const [open, setOpen] = useState(false);\n const addItem = useFilterAddItem({\n disabledReason,\n hasOptions: !!items.length || !!onSearchChange,\n isEmpty: !value.length,\n label,\n });\n\n useFilterRegistration(value, resetValue, onValueChange);\n\n // Remember every option seen, so a selection keeps its label, group and icon once a search has replaced `items`.\n const knownItems = useRef(new Map<string, BitkitFilterSelectItem>());\n items.forEach((item) => knownItems.current.set(item.value, item));\n\n // A filter just added through \"Add filter\" hands focus to its new chip as its panel closes.\n const triggerRef = useRef<HTMLButtonElement>(null);\n const setRef = useMemo(() => mergeRefs<HTMLButtonElement>(ref, triggerRef), [ref]);\n const isFocusPending = useRef(false);\n // A filter emptied from its own chip loses the chip, so its panel hands focus to \"Add filter\" on close.\n const isEmptiedFromChip = useRef(false);\n\n // Debounced here rather than in the form, which outlives the close by its exit animation: closing\n // drops a pending search, so it can't land after the reset to `''`. Clearing goes through right away.\n const searchTimeout = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => () => clearTimeout(searchTimeout.current), []);\n const search = (text: string) => {\n clearTimeout(searchTimeout.current);\n if (text) searchTimeout.current = setTimeout(() => onSearchChange?.(text), SEARCH_DEBOUNCE_MS);\n else onSearchChange?.('');\n };\n\n const onOpenChange = (isOpen: boolean) => {\n setOpen(isOpen);\n if (!isOpen && onSearchChange) search('');\n };\n\n const form = (isAdding: boolean) => (\n <FilterSelectForm\n isEditing={!!value.length}\n isOrderFixed={preserveOrder}\n isRequired={required && !addItem}\n items={items}\n label={label}\n loading={loading}\n loadingLabel={loadingLabel}\n multiple={multiple}\n onApply={(next) => {\n if (isAdding) isFocusPending.current = true;\n onValueChange(next);\n if (isAdding) addItem?.stopAdding();\n else if (addItem && !next.length) isEmptiedFromChip.current = true;\n onOpenChange(false);\n }}\n onCancel={() => {\n if (isAdding) addItem?.stopAdding();\n onOpenChange(false);\n }}\n onSearchChange={onSearchChange ? search : undefined}\n pattern={pattern}\n pluralLabel={pluralLabel}\n searchPlaceholder={searchPlaceholder}\n selectedItems={value\n .filter((selected) => !isPattern(selected))\n .map((selected) => knownItems.current.get(selected) ?? { label: selected, value: selected })}\n value={value}\n />\n );\n\n // Inside `Add`, an empty filter has no chip: it is listed in the menu, and its panel opens from\n // there, anchored to the \"Add filter\" button. It stays mounted once a value is applied, so it can\n // close (and hand over focus) the usual way.\n const addPanel = addItem ? (\n <FilterPanel\n finalFocusEl={() => {\n const chip = isFocusPending.current ? triggerRef.current : null;\n isFocusPending.current = false;\n return chip ?? addItem.getTrigger();\n }}\n getAnchorElement={addItem.getTrigger}\n onOpenChange={(isOpen) => {\n if (isOpen) return;\n addItem.stopAdding();\n onOpenChange(false);\n }}\n open={addItem.isAdding}\n >\n {form(true)}\n </FilterPanel>\n ) : null;\n\n const emptyText = emptyLabel ?? `All ${toRunningText(pluralLabel)}`;\n const singleText = value.length === 1 ? (knownItems.current.get(value[0])?.label ?? value[0]) : '';\n const onRemove = addItem\n ? () => {\n onValueChange([]);\n addItem.focusTrigger();\n }\n : undefined;\n\n // Inside `Add`, an empty filter has no chip of its own.\n const hasChip = !addItem || !!value.length;\n let trigger = null;\n if (hasChip && isMobile) {\n let fieldValue = emptyText;\n if (value.length > 1) fieldValue = `${value.length} selected`;\n else if (value.length) fieldValue = singleText;\n trigger = (\n <FilterField\n {...rest}\n isOpen={open}\n label={multiple ? pluralLabel : label}\n onClick={() => onOpenChange(true)}\n onRemove={onRemove}\n ref={setRef}\n value={fieldValue}\n />\n );\n } else if (hasChip) {\n let chipProps: FilterChipProps = { value: emptyText };\n if (value.length > 1) chipProps = { label: toRunningText(pluralLabel), labelAfter: true, value: value.length };\n else if (value.length) chipProps = { label: `${label}:`, value: singleText };\n trigger = (\n <FilterChip {...chipProps} onRemove={onRemove} ref={setRef} removeLabel={`Remove ${label} filter`} {...rest} />\n );\n }\n\n // Emptied from its own chip, the chip goes, so focus moves to \"Add filter\", like on remove. Handed over\n // as the panel closes: on mobile, earlier would lose it to the closing view's focus trap.\n const chipPanelFinalFocusEl = addItem\n ? () => {\n if (!isEmptiedFromChip.current) return null;\n isEmptiedFromChip.current = false;\n const addTrigger = addItem.getTrigger();\n if (addTrigger instanceof HTMLButtonElement && !addTrigger.disabled) return addTrigger;\n addItem.focusTrigger();\n return null;\n }\n : undefined;\n\n // Both panels stay mounted whether or not a value is applied (the chip's one without its chip), so\n // neither is remounted, and each can still close and hand over focus once the value changes.\n return (\n <>\n <FilterPanel finalFocusEl={chipPanelFinalFocusEl} onOpenChange={onOpenChange} open={open} trigger={trigger}>\n {form(false)}\n </FilterPanel>\n {addPanel}\n </>\n );\n});\n\nBitkitFilterSelect.displayName = 'BitkitFilterSelect';\n\nexport default BitkitFilterSelect;\n"],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- import { BitkitIconComponent } from '../../icons';
3
- import { BitkitColorToken } from '../../theme/themeUtils';
4
- export interface BitkitFilterSwitchItem {
5
- icon?: BitkitIconComponent;
6
- /** Colors the icon, e.g. a status: `icon/positive` for "Passed". Defaults to the switch's own icon color. */
7
- iconColor?: BitkitColorToken<'icon'>;
8
- label: string;
9
- value: string;
10
- }
11
- export interface BitkitFilterSwitchProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {
12
- /** Label of the leading option that removes the filter. Defaults to "All". */
13
- allLabel?: string;
14
- items: BitkitFilterSwitchItem[];
15
- /** Accessible name of the switch, e.g. "Platform". */
16
- label: string;
17
- /** Called on every click. `null` is the leading "All" option. */
18
- onValueChange: (value: string | null) => void;
19
- /** The value "Clear filters" restores. Defaults to "All". */
20
- resetValue?: string | null;
21
- value: string | null;
22
- }
23
- /**
24
- * A filter with a few mutually exclusive options, applied on click. Its first option is "All". On
25
- * mobile it is a field opening a single-select list, like `BitkitFilter.Select`.
26
- */
27
- declare const BitkitFilterSwitch: import('react').ForwardRefExoticComponent<BitkitFilterSwitchProps & import('react').RefAttributes<HTMLElement>>;
28
- export default BitkitFilterSwitch;
@@ -1,87 +0,0 @@
1
- import { useFilterContext, useFilterRegistration } from "./BitkitFilter.context.js";
2
- import FilterField from "./components/FilterField.js";
3
- import FilterPanel from "./components/FilterPanel.js";
4
- import FilterSelectForm from "./components/FilterSelectForm.js";
5
- import { forwardRef, useId, useMemo, useState } from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
- import { mergeRefs } from "@chakra-ui/react";
8
- import { SegmentGroup } from "@chakra-ui/react/segment-group";
9
- //#region lib/components/BitkitFilter/BitkitFilterSwitch.tsx
10
- /**
11
- * A filter with a few mutually exclusive options, applied on click. Its first option is "All". On
12
- * mobile it is a field opening a single-select list, like `BitkitFilter.Select`.
13
- */
14
- var BitkitFilterSwitch = forwardRef((props, ref) => {
15
- const { allLabel = "All", css, items, label, onValueChange, resetValue = null, value, ...rest } = props;
16
- const { isDisabled, isMobile, styles } = useFilterContext();
17
- const [open, setOpen] = useState(false);
18
- const ALL = `all-${useId()}`;
19
- const setRef = useMemo(() => mergeRefs(ref), [ref]);
20
- useFilterRegistration(value, resetValue, onValueChange);
21
- if (isMobile) {
22
- const options = [{
23
- label: allLabel,
24
- value: ALL
25
- }, ...items];
26
- return /* @__PURE__ */ jsx(FilterPanel, {
27
- onOpenChange: setOpen,
28
- open,
29
- trigger: /* @__PURE__ */ jsx(FilterField, {
30
- ...rest,
31
- css,
32
- isOpen: open,
33
- label,
34
- onClick: () => setOpen(true),
35
- ref: setRef,
36
- value: items.find((item) => item.value === value)?.label ?? allLabel
37
- }),
38
- children: /* @__PURE__ */ jsx(FilterSelectForm, {
39
- isEditing: value !== null,
40
- isOrderFixed: true,
41
- items: options,
42
- label,
43
- onApply: ([next]) => {
44
- onValueChange(!next || next === ALL ? null : next);
45
- setOpen(false);
46
- },
47
- onCancel: () => setOpen(false),
48
- pluralLabel: label,
49
- value: [value ?? ALL]
50
- })
51
- });
52
- }
53
- return /* @__PURE__ */ jsx(SegmentGroup.Root, {
54
- "aria-label": label,
55
- css: [styles.switch, css],
56
- readOnly: isDisabled,
57
- onValueChange: (details) => onValueChange(!details.value || details.value === ALL ? null : details.value),
58
- ref: setRef,
59
- unstyled: true,
60
- value: value ?? ALL,
61
- ...rest,
62
- children: [{
63
- label: allLabel,
64
- value: ALL
65
- }, ...items].map((item) => /* @__PURE__ */ jsxs(SegmentGroup.Item, {
66
- css: styles.switchItem,
67
- value: item.value,
68
- children: [
69
- !!item.icon && /* @__PURE__ */ jsx(item.icon, {
70
- "data-own-color": item.iconColor ? "" : void 0,
71
- color: item.iconColor,
72
- size: "16"
73
- }),
74
- /* @__PURE__ */ jsx(SegmentGroup.ItemText, {
75
- css: styles.switchItemText,
76
- children: item.label
77
- }),
78
- /* @__PURE__ */ jsx(SegmentGroup.ItemHiddenInput, { disabled: isDisabled ? false : void 0 })
79
- ]
80
- }, item.value))
81
- });
82
- });
83
- BitkitFilterSwitch.displayName = "BitkitFilterSwitch";
84
- //#endregion
85
- export { BitkitFilterSwitch as default };
86
-
87
- //# sourceMappingURL=BitkitFilterSwitch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BitkitFilterSwitch.js","names":[],"sources":["../../../lib/components/BitkitFilter/BitkitFilterSwitch.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { mergeRefs } from '@chakra-ui/react';\nimport { type BoxProps } from '@chakra-ui/react/box';\nimport { SegmentGroup } from '@chakra-ui/react/segment-group';\nimport { forwardRef, useId, useMemo, useState } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport { type BitkitColorToken } from '../../theme/themeUtils';\nimport { useFilterContext, useFilterRegistration } from './BitkitFilter.context';\nimport FilterField from './components/FilterField';\nimport FilterPanel from './components/FilterPanel';\nimport FilterSelectForm from './components/FilterSelectForm';\n\nexport interface BitkitFilterSwitchItem {\n icon?: BitkitIconComponent;\n /** Colors the icon, e.g. a status: `icon/positive` for \"Passed\". Defaults to the switch's own icon color. */\n iconColor?: BitkitColorToken<'icon'>;\n label: string;\n value: string;\n}\n\nexport interface BitkitFilterSwitchProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {\n /** Label of the leading option that removes the filter. Defaults to \"All\". */\n allLabel?: string;\n items: BitkitFilterSwitchItem[];\n /** Accessible name of the switch, e.g. \"Platform\". */\n label: string;\n /** Called on every click. `null` is the leading \"All\" option. */\n onValueChange: (value: string | null) => void;\n /** The value \"Clear filters\" restores. Defaults to \"All\". */\n resetValue?: string | null;\n value: string | null;\n}\n\n/**\n * A filter with a few mutually exclusive options, applied on click. Its first option is \"All\". On\n * mobile it is a field opening a single-select list, like `BitkitFilter.Select`.\n */\n// The ref lands on the switch on desktop, and on the field's button on mobile.\nconst BitkitFilterSwitch = forwardRef<HTMLElement, BitkitFilterSwitchProps>((props, ref) => {\n const { allLabel = 'All', css, items, label, onValueChange, resetValue = null, value, ...rest } = props;\n\n const { isDisabled, isMobile, styles } = useFilterContext();\n const [open, setOpen] = useState(false);\n // Stands in for `null` in the segment group, which needs a string value per item. Per instance,\n // so no item value can collide with it.\n const ALL = `all-${useId()}`;\n // A callback ref takes either element, where the forwarded `HTMLElement` ref object doesn't type-check.\n const setRef = useMemo(() => mergeRefs<HTMLElement>(ref), [ref]);\n\n useFilterRegistration(value, resetValue, onValueChange);\n\n if (isMobile) {\n const options = [{ label: allLabel, value: ALL }, ...items];\n return (\n <FilterPanel\n onOpenChange={setOpen}\n open={open}\n trigger={\n <FilterField\n {...rest}\n css={css}\n isOpen={open}\n label={label}\n onClick={() => setOpen(true)}\n ref={setRef}\n value={items.find((item) => item.value === value)?.label ?? allLabel}\n />\n }\n >\n <FilterSelectForm\n isEditing={value !== null}\n isOrderFixed\n items={options}\n label={label}\n onApply={([next]) => {\n onValueChange(!next || next === ALL ? null : next);\n setOpen(false);\n }}\n onCancel={() => setOpen(false)}\n pluralLabel={label}\n value={[value ?? ALL]}\n />\n </FilterPanel>\n );\n }\n\n // Figma's `filterSwitch` is its own component, so the segment group is unstyled and takes the\n // filter recipe instead of `BitkitSegmentedControl`'s look.\n return (\n <SegmentGroup.Root\n aria-label={label}\n css={[styles.switch, css]}\n readOnly={isDisabled}\n onValueChange={(details) => onValueChange(!details.value || details.value === ALL ? null : details.value)}\n ref={setRef}\n unstyled\n value={value ?? ALL}\n {...rest}\n >\n {[{ label: allLabel, value: ALL } as BitkitFilterSwitchItem, ...items].map((item) => (\n <SegmentGroup.Item css={styles.switchItem} key={item.value} value={item.value}>\n {!!item.icon && (\n <item.icon data-own-color={item.iconColor ? '' : undefined} color={item.iconColor} size=\"16\" />\n )}\n <SegmentGroup.ItemText css={styles.switchItemText}>{item.label}</SegmentGroup.ItemText>\n {/* Zag disables a read-only group's radios, which would drop a focus handed to one while the\n page loads; kept enabled, Zag's read-only guard still refuses the change. */}\n <SegmentGroup.ItemHiddenInput disabled={isDisabled ? false : undefined} />\n </SegmentGroup.Item>\n ))}\n </SegmentGroup.Root>\n );\n});\n\nBitkitFilterSwitch.displayName = 'BitkitFilterSwitch';\n\nexport default BitkitFilterSwitch;\n"],"mappings":";;;;;;;;;;;;;AAuCA,IAAM,qBAAqB,YAAkD,OAAO,QAAQ;CAC1F,MAAM,EAAE,WAAW,OAAO,KAAK,OAAO,OAAO,eAAe,aAAa,MAAM,OAAO,GAAG,SAAS;CAElG,MAAM,EAAE,YAAY,UAAU,WAAW,iBAAiB;CAC1D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAGtC,MAAM,MAAM,OAAO,MAAM;CAEzB,MAAM,SAAS,cAAc,UAAuB,GAAG,GAAG,CAAC,GAAG,CAAC;CAE/D,sBAAsB,OAAO,YAAY,aAAa;CAEtD,IAAI,UAAU;EACZ,MAAM,UAAU,CAAC;GAAE,OAAO;GAAU,OAAO;EAAI,GAAG,GAAG,KAAK;EAC1D,OACE,oBAAC,aAAD;GACE,cAAc;GACR;GACN,SACE,oBAAC,aAAD;IACE,GAAI;IACC;IACL,QAAQ;IACD;IACP,eAAe,QAAQ,IAAI;IAC3B,KAAK;IACL,OAAO,MAAM,MAAM,SAAS,KAAK,UAAU,KAAK,CAAC,EAAE,SAAS;GAC7D,CAAA;GAGH,UAAA,oBAAC,kBAAD;IACE,WAAW,UAAU;IACrB,cAAA;IACA,OAAO;IACA;IACP,UAAU,CAAC,UAAU;KACnB,cAAc,CAAC,QAAQ,SAAS,MAAM,OAAO,IAAI;KACjD,QAAQ,KAAK;IACf;IACA,gBAAgB,QAAQ,KAAK;IAC7B,aAAa;IACb,OAAO,CAAC,SAAS,GAAG;GACrB,CAAA;EACU,CAAA;CAEjB;CAIA,OACE,oBAAC,aAAa,MAAd;EACE,cAAY;EACZ,KAAK,CAAC,OAAO,QAAQ,GAAG;EACxB,UAAU;EACV,gBAAgB,YAAY,cAAc,CAAC,QAAQ,SAAS,QAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;EACxG,KAAK;EACL,UAAA;EACA,OAAO,SAAS;EAChB,GAAI;EAEH,UAAA,CAAC;GAAE,OAAO;GAAU,OAAO;EAAI,GAA6B,GAAG,KAAK,CAAC,CAAC,KAAK,SAC1E,qBAAC,aAAa,MAAd;GAAmB,KAAK,OAAO;GAA6B,OAAO,KAAK;GAAxE,UAAA;IACG,CAAC,CAAC,KAAK,QACN,oBAAC,KAAK,MAAN;KAAW,kBAAgB,KAAK,YAAY,KAAK,KAAA;KAAW,OAAO,KAAK;KAAW,MAAK;IAAM,CAAA;IAEhG,oBAAC,aAAa,UAAd;KAAuB,KAAK,OAAO;KAAiB,UAAA,KAAK;IAA6B,CAAA;IAGtF,oBAAC,aAAa,iBAAd,EAA8B,UAAU,aAAa,QAAQ,KAAA,EAAY,CAAA;GACxD;EAR6B,GAAA,KAAK,KAQlC,CACpB;CACgB,CAAA;AAEvB,CAAC;AAED,mBAAmB,cAAc"}
@@ -1,23 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- import { ReactElement, ReactNode } from 'react';
3
- import { BitkitIconComponent } from '../../../icons';
4
- export interface FilterChipProps extends Omit<BoxProps, 'children'> {
5
- /** Muted text before `value` — the filter's label (`Workflow:`), or the noun after a count. */
6
- label?: string;
7
- icon?: BitkitIconComponent;
8
- /** Puts `label` after `value`, for a count: `2 workflows`. */
9
- labelAfter?: boolean;
10
- /** Turns the chevron into a separate remove button. */
11
- onRemove?: () => void;
12
- /** Accessible name of the remove button. */
13
- removeLabel?: string;
14
- /**
15
- * Wraps the chip's button in whatever opens its popover. Defaults to `Popover.Trigger`, so the
16
- * chip must render inside a `Popover.Root` unless this is given.
17
- */
18
- renderTrigger?: (button: ReactElement) => ReactNode;
19
- value: ReactNode;
20
- }
21
- /** The chip a filter shows in the bar: a button opening the filter's popover, and an optional remove button. */
22
- declare const FilterChip: import('react').ForwardRefExoticComponent<FilterChipProps & import('react').RefAttributes<HTMLButtonElement>>;
23
- export default FilterChip;
@@ -1,66 +0,0 @@
1
- import IconChevronDown from "../../../icons/IconChevronDown.js";
2
- import IconCross from "../../../icons/IconCross.js";
3
- import { useFilterContext } from "../BitkitFilter.context.js";
4
- import { Box } from "@chakra-ui/react/box";
5
- import { chakra } from "@chakra-ui/react/styled-system";
6
- import { forwardRef } from "react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- import { Text } from "@chakra-ui/react/text";
9
- import { Popover } from "@chakra-ui/react/popover";
10
- //#region lib/components/BitkitFilter/components/FilterChip.tsx
11
- var asPopoverTrigger = (button) => /* @__PURE__ */ jsx(Popover.Trigger, {
12
- asChild: true,
13
- children: button
14
- });
15
- /** The chip a filter shows in the bar: a button opening the filter's popover, and an optional remove button. */
16
- var FilterChip = forwardRef((props, ref) => {
17
- const { css, icon: Icon, label, labelAfter, onRemove, removeLabel, renderTrigger = asPopoverTrigger, value, ...rest } = props;
18
- const { isDisabled, styles } = useFilterContext();
19
- const labelNode = label ? /* @__PURE__ */ jsx(Text, {
20
- as: "span",
21
- css: styles.chipLabel,
22
- children: label
23
- }) : null;
24
- return /* @__PURE__ */ jsxs(Box, {
25
- css: [styles.chip, css],
26
- ...rest,
27
- children: [renderTrigger(/* @__PURE__ */ jsxs(chakra.button, {
28
- "aria-disabled": isDisabled || void 0,
29
- "data-disabled": isDisabled ? "" : void 0,
30
- css: styles.chipTrigger,
31
- ref,
32
- type: "button",
33
- children: [
34
- !!Icon && /* @__PURE__ */ jsx(Icon, {
35
- css: styles.chipIcon,
36
- "data-chip-icon": true,
37
- size: "16"
38
- }),
39
- !labelAfter && labelNode,
40
- /* @__PURE__ */ jsx(Text, {
41
- as: "span",
42
- css: styles.chipValue,
43
- children: value
44
- }),
45
- labelAfter && labelNode,
46
- !onRemove && /* @__PURE__ */ jsx(IconChevronDown, {
47
- css: styles.chipChevron,
48
- size: "16"
49
- })
50
- ]
51
- })), !!onRemove && /* @__PURE__ */ jsx(chakra.button, {
52
- "aria-label": removeLabel,
53
- "aria-disabled": isDisabled || void 0,
54
- "data-disabled": isDisabled ? "" : void 0,
55
- css: styles.chipRemove,
56
- onClick: isDisabled ? void 0 : onRemove,
57
- type: "button",
58
- children: /* @__PURE__ */ jsx(IconCross, { size: "16" })
59
- })]
60
- });
61
- });
62
- FilterChip.displayName = "FilterChip";
63
- //#endregion
64
- export { FilterChip as default };
65
-
66
- //# sourceMappingURL=FilterChip.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FilterChip.js","names":[],"sources":["../../../../lib/components/BitkitFilter/components/FilterChip.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { Popover } from '@chakra-ui/react/popover';\n// `chakra.button`: the chip's two halves are bare buttons styled by the filter recipe; BitkitButton's\n// recipe would fight the chip's own border, height and hover.\nimport { chakra } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type ReactElement, type ReactNode } from 'react';\n\nimport { type BitkitIconComponent, IconChevronDown, IconCross } from '../../../icons';\nimport { useFilterContext } from '../BitkitFilter.context';\n\nexport interface FilterChipProps extends Omit<BoxProps, 'children'> {\n /** Muted text before `value` — the filter's label (`Workflow:`), or the noun after a count. */\n label?: string;\n icon?: BitkitIconComponent;\n /** Puts `label` after `value`, for a count: `2 workflows`. */\n labelAfter?: boolean;\n /** Turns the chevron into a separate remove button. */\n onRemove?: () => void;\n /** Accessible name of the remove button. */\n removeLabel?: string;\n /**\n * Wraps the chip's button in whatever opens its popover. Defaults to `Popover.Trigger`, so the\n * chip must render inside a `Popover.Root` unless this is given.\n */\n renderTrigger?: (button: ReactElement) => ReactNode;\n value: ReactNode;\n}\n\nconst asPopoverTrigger = (button: ReactElement) => <Popover.Trigger asChild>{button}</Popover.Trigger>;\n\n/** The chip a filter shows in the bar: a button opening the filter's popover, and an optional remove button. */\nconst FilterChip = forwardRef<HTMLButtonElement, FilterChipProps>((props, ref) => {\n const {\n css,\n icon: Icon,\n label,\n labelAfter,\n onRemove,\n removeLabel,\n renderTrigger = asPopoverTrigger,\n value,\n ...rest\n } = props;\n const { isDisabled, styles } = useFilterContext();\n\n const labelNode = label ? (\n <Text as=\"span\" css={styles.chipLabel}>\n {label}\n </Text>\n ) : null;\n\n return (\n <Box css={[styles.chip, css]} {...rest}>\n {renderTrigger(\n // `aria-disabled` while the page loads, not `disabled`: a focus handed to the chip has to stay on it.\n // The panel ignores opening meanwhile.\n <chakra.button\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? '' : undefined}\n css={styles.chipTrigger}\n ref={ref}\n type=\"button\"\n >\n {!!Icon && <Icon css={styles.chipIcon} data-chip-icon size=\"16\" />}\n {!labelAfter && labelNode}\n <Text as=\"span\" css={styles.chipValue}>\n {value}\n </Text>\n {labelAfter && labelNode}\n {!onRemove && <IconChevronDown css={styles.chipChevron} size=\"16\" />}\n </chakra.button>,\n )}\n {!!onRemove && (\n <chakra.button\n aria-label={removeLabel}\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? '' : undefined}\n css={styles.chipRemove}\n onClick={isDisabled ? undefined : onRemove}\n type=\"button\"\n >\n <IconCross size=\"16\" />\n </chakra.button>\n )}\n </Box>\n );\n});\n\nFilterChip.displayName = 'FilterChip';\n\nexport default FilterChip;\n"],"mappings":";;;;;;;;;;AA6BA,IAAM,oBAAoB,WAAyB,oBAAC,QAAQ,SAAT;CAAiB,SAAA;CAAS,UAAA;AAAwB,CAAA;;AAGrG,IAAM,aAAa,YAAgD,OAAO,QAAQ;CAChF,MAAM,EACJ,KACA,MAAM,MACN,OACA,YACA,UACA,aACA,gBAAgB,kBAChB,OACA,GAAG,SACD;CACJ,MAAM,EAAE,YAAY,WAAW,iBAAiB;CAEhD,MAAM,YAAY,QAChB,oBAAC,MAAD;EAAM,IAAG;EAAO,KAAK,OAAO;EACzB,UAAA;CACG,CAAA,IACJ;CAEJ,OACE,qBAAC,KAAD;EAAK,KAAK,CAAC,OAAO,MAAM,GAAG;EAAG,GAAI;EAAlC,UAAA,CACG,cAGC,qBAAC,OAAO,QAAR;GACE,iBAAe,cAAc,KAAA;GAC7B,iBAAe,aAAa,KAAK,KAAA;GACjC,KAAK,OAAO;GACP;GACL,MAAK;GALP,UAAA;IAOG,CAAC,CAAC,QAAQ,oBAAC,MAAD;KAAM,KAAK,OAAO;KAAU,kBAAA;KAAe,MAAK;IAAM,CAAA;IAChE,CAAC,cAAc;IAChB,oBAAC,MAAD;KAAM,IAAG;KAAO,KAAK,OAAO;KACzB,UAAA;IACG,CAAA;IACL,cAAc;IACd,CAAC,YAAY,oBAAC,iBAAD;KAAiB,KAAK,OAAO;KAAa,MAAK;IAAM,CAAA;GACtD;EACjB,CAAA,CAAA,GACC,CAAC,CAAC,YACD,oBAAC,OAAO,QAAR;GACE,cAAY;GACZ,iBAAe,cAAc,KAAA;GAC7B,iBAAe,aAAa,KAAK,KAAA;GACjC,KAAK,OAAO;GACZ,SAAS,aAAa,KAAA,IAAY;GAClC,MAAK;GAEL,UAAA,oBAAC,WAAD,EAAW,MAAK,KAAM,CAAA;EACT,CAAA,CAEd;;AAET,CAAC;AAED,WAAW,cAAc"}
@@ -1,15 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- import { BitkitIconComponent } from '../../../icons';
3
- export interface FilterFieldProps extends Omit<BoxProps, 'children' | 'onClick'> {
4
- icon?: BitkitIconComponent;
5
- /** The view it opens is open. */
6
- isOpen: boolean;
7
- label: string;
8
- onClick: () => void;
9
- /** Turns the chevron into a separate remove button, for a filter added through "Add filter". */
10
- onRemove?: () => void;
11
- value: string;
12
- }
13
- /** A filter in the mobile filters dialog: its label, and a row showing its value that opens its view. */
14
- declare const FilterField: import('react').ForwardRefExoticComponent<FilterFieldProps & import('react').RefAttributes<HTMLButtonElement>>;
15
- export default FilterField;
@@ -1,60 +0,0 @@
1
- import IconChevronRight from "../../../icons/IconChevronRight.js";
2
- import IconCross from "../../../icons/IconCross.js";
3
- import { useFilterContext } from "../BitkitFilter.context.js";
4
- import { Box } from "@chakra-ui/react/box";
5
- import { chakra } from "@chakra-ui/react/styled-system";
6
- import { forwardRef, useId } from "react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- import { Text } from "@chakra-ui/react/text";
9
- //#region lib/components/BitkitFilter/components/FilterField.tsx
10
- /** A filter in the mobile filters dialog: its label, and a row showing its value that opens its view. */
11
- var FilterField = forwardRef(({ css, icon: Icon, isOpen, label, onClick, onRemove, value, ...rest }, ref) => {
12
- const { isDisabled, styles } = useFilterContext();
13
- const labelId = useId();
14
- const valueId = useId();
15
- return /* @__PURE__ */ jsxs(Box, {
16
- css: [styles.field, css],
17
- ...rest,
18
- children: [/* @__PURE__ */ jsx(Text, {
19
- css: styles.fieldLabel,
20
- id: labelId,
21
- children: label
22
- }), /* @__PURE__ */ jsxs(Box, {
23
- css: styles.fieldControl,
24
- children: [/* @__PURE__ */ jsxs(chakra.button, {
25
- "aria-expanded": isOpen,
26
- "aria-haspopup": "dialog",
27
- "aria-labelledby": `${labelId} ${valueId}`,
28
- "aria-disabled": isDisabled || void 0,
29
- "data-disabled": isDisabled ? "" : void 0,
30
- css: styles.fieldTrigger,
31
- onClick: isDisabled ? void 0 : onClick,
32
- ref,
33
- type: "button",
34
- children: [
35
- !!Icon && /* @__PURE__ */ jsx(Icon, { css: styles.fieldIcon }),
36
- /* @__PURE__ */ jsx(Text, {
37
- as: "span",
38
- css: styles.fieldValue,
39
- id: valueId,
40
- children: value
41
- }),
42
- !onRemove && /* @__PURE__ */ jsx(IconChevronRight, { css: styles.fieldChevron })
43
- ]
44
- }), !!onRemove && /* @__PURE__ */ jsx(chakra.button, {
45
- "aria-label": `Remove ${label} filter`,
46
- "aria-disabled": isDisabled || void 0,
47
- "data-disabled": isDisabled ? "" : void 0,
48
- css: styles.fieldRemove,
49
- onClick: isDisabled ? void 0 : onRemove,
50
- type: "button",
51
- children: /* @__PURE__ */ jsx(IconCross, {})
52
- })]
53
- })]
54
- });
55
- });
56
- FilterField.displayName = "FilterField";
57
- //#endregion
58
- export { FilterField as default };
59
-
60
- //# sourceMappingURL=FilterField.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FilterField.js","names":[],"sources":["../../../../lib/components/BitkitFilter/components/FilterField.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\n// `chakra.button`: like the desktop chip, the field's halves are bare buttons styled by the filter recipe.\nimport { chakra } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, useId } from 'react';\n\nimport { type BitkitIconComponent, IconChevronRight, IconCross } from '../../../icons';\nimport { useFilterContext } from '../BitkitFilter.context';\n\nexport interface FilterFieldProps extends Omit<BoxProps, 'children' | 'onClick'> {\n icon?: BitkitIconComponent;\n /** The view it opens is open. */\n isOpen: boolean;\n label: string;\n onClick: () => void;\n /** Turns the chevron into a separate remove button, for a filter added through \"Add filter\". */\n onRemove?: () => void;\n value: string;\n}\n\n/** A filter in the mobile filters dialog: its label, and a row showing its value that opens its view. */\nconst FilterField = forwardRef<HTMLButtonElement, FilterFieldProps>(\n ({ css, icon: Icon, isOpen, label, onClick, onRemove, value, ...rest }, ref) => {\n const { isDisabled, styles } = useFilterContext();\n const labelId = useId();\n const valueId = useId();\n\n return (\n <Box css={[styles.field, css]} {...rest}>\n <Text css={styles.fieldLabel} id={labelId}>\n {label}\n </Text>\n <Box css={styles.fieldControl}>\n <chakra.button\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n aria-labelledby={`${labelId} ${valueId}`}\n // `aria-disabled` while the page loads, so a focus handed to the field stays on it.\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? '' : undefined}\n css={styles.fieldTrigger}\n onClick={isDisabled ? undefined : onClick}\n ref={ref}\n type=\"button\"\n >\n {!!Icon && <Icon css={styles.fieldIcon} />}\n <Text as=\"span\" css={styles.fieldValue} id={valueId}>\n {value}\n </Text>\n {!onRemove && <IconChevronRight css={styles.fieldChevron} />}\n </chakra.button>\n {!!onRemove && (\n <chakra.button\n aria-label={`Remove ${label} filter`}\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? '' : undefined}\n css={styles.fieldRemove}\n onClick={isDisabled ? undefined : onRemove}\n type=\"button\"\n >\n <IconCross />\n </chakra.button>\n )}\n </Box>\n </Box>\n );\n },\n);\n\nFilterField.displayName = 'FilterField';\n\nexport default FilterField;\n"],"mappings":";;;;;;;;;;AAqBA,IAAM,cAAc,YACjB,EAAE,KAAK,MAAM,MAAM,QAAQ,OAAO,SAAS,UAAU,OAAO,GAAG,QAAQ,QAAQ;CAC9E,MAAM,EAAE,YAAY,WAAW,iBAAiB;CAChD,MAAM,UAAU,MAAM;CACtB,MAAM,UAAU,MAAM;CAEtB,OACE,qBAAC,KAAD;EAAK,KAAK,CAAC,OAAO,OAAO,GAAG;EAAG,GAAI;EAAnC,UAAA,CACE,oBAAC,MAAD;GAAM,KAAK,OAAO;GAAY,IAAI;GAC/B,UAAA;EACG,CAAA,GACN,qBAAC,KAAD;GAAK,KAAK,OAAO;GAAjB,UAAA,CACE,qBAAC,OAAO,QAAR;IACE,iBAAe;IACf,iBAAc;IACd,mBAAiB,GAAG,QAAQ,GAAG;IAE/B,iBAAe,cAAc,KAAA;IAC7B,iBAAe,aAAa,KAAK,KAAA;IACjC,KAAK,OAAO;IACZ,SAAS,aAAa,KAAA,IAAY;IAC7B;IACL,MAAK;IAVP,UAAA;KAYG,CAAC,CAAC,QAAQ,oBAAC,MAAD,EAAM,KAAK,OAAO,UAAY,CAAA;KACzC,oBAAC,MAAD;MAAM,IAAG;MAAO,KAAK,OAAO;MAAY,IAAI;MACzC,UAAA;KACG,CAAA;KACL,CAAC,YAAY,oBAAC,kBAAD,EAAkB,KAAK,OAAO,aAAe,CAAA;IAC9C;GACd,CAAA,GAAA,CAAC,CAAC,YACD,oBAAC,OAAO,QAAR;IACE,cAAY,UAAU,MAAM;IAC5B,iBAAe,cAAc,KAAA;IAC7B,iBAAe,aAAa,KAAK,KAAA;IACjC,KAAK,OAAO;IACZ,SAAS,aAAa,KAAA,IAAY;IAClC,MAAK;IAEL,UAAA,oBAAC,WAAD,CAAY,CAAA;GACC,CAAA,CAEd;EACF,CAAA,CAAA;;AAET,CACF;AAEA,YAAY,cAAc"}
@@ -1,42 +0,0 @@
1
- import { ReactNode } from 'react';
2
- export interface FilterPanelProps {
3
- children: ReactNode;
4
- /** Where focus goes on close, for a panel without a trigger to return it to. */
5
- finalFocusEl?: () => HTMLElement | null;
6
- /** Anchors the desktop popover to an element it has no trigger for — the "Add filter" button. */
7
- getAnchorElement?: () => HTMLElement | null;
8
- onOpenChange: (open: boolean) => void;
9
- open: boolean;
10
- /**
11
- * What opens the panel: on desktop a `FilterChip`, which renders the popover's trigger; on mobile a
12
- * `FilterField`, which opens it through its own `onClick`.
13
- */
14
- trigger?: ReactNode;
15
- }
16
- /**
17
- * Where a filter edits its value: an anchored popover on desktop, a full-screen view stacked over the
18
- * filters dialog on mobile. The content unmounts on close, so the draft state of the form inside
19
- * starts over from the applied value each time it opens.
20
- */
21
- declare const FilterPanel: (props: FilterPanelProps) => import('react').JSX.Element;
22
- export interface FilterPanelHeaderProps {
23
- /** Desktop only: a multi-select's selection count, shown as a badge next to the title. */
24
- count?: number;
25
- title: string;
26
- }
27
- export declare const FilterPanelHeader: ({ count, title }: FilterPanelHeaderProps) => import('react').JSX.Element;
28
- export interface FilterPanelFooterProps {
29
- /** Mobile only: the Apply button's label, e.g. "Apply (2)". */
30
- applyLabel?: string;
31
- isApplyDisabled: boolean;
32
- onApply: () => void;
33
- /** Desktop only: adds a "Cancel" button. On mobile the header's back button cancels. */
34
- onCancel?: () => void;
35
- /** The action before Apply: "Clear", or the wildcard-mode switch. */
36
- start?: {
37
- label: string;
38
- onClick: () => void;
39
- };
40
- }
41
- export declare const FilterPanelFooter: ({ applyLabel, isApplyDisabled, onApply, onCancel, start, }: FilterPanelFooterProps) => import('react').JSX.Element;
42
- export default FilterPanel;