@bitrise/bitkit-v2 0.3.481-beta.3057 → 0.3.481-beta.3061

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 (136) 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 +112 -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 +23 -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 +32 -0
  46. package/dist/components/BitkitUIHeader/UIHeaderButton.js +41 -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 +71 -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/slot-recipes/DatePicker.recipe.d.ts +0 -15
  70. package/dist/theme/slot-recipes/DatePicker.recipe.js +22 -72
  71. package/dist/theme/slot-recipes/DatePicker.recipe.js.map +1 -1
  72. package/dist/theme/slot-recipes/DatePickerSelect.recipe.d.ts +0 -85
  73. package/dist/theme/slot-recipes/DatePickerSelect.recipe.js +10 -35
  74. package/dist/theme/slot-recipes/DatePickerSelect.recipe.js.map +1 -1
  75. package/dist/theme/slot-recipes/Menu.recipe.js +1 -6
  76. package/dist/theme/slot-recipes/Menu.recipe.js.map +1 -1
  77. package/dist/theme/slot-recipes/Tag.recipe.d.ts +1 -1
  78. package/dist/theme/slot-recipes/UIHeader.recipe.d.ts +4 -0
  79. package/dist/theme/slot-recipes/UIHeader.recipe.js +241 -0
  80. package/dist/theme/slot-recipes/UIHeader.recipe.js.map +1 -0
  81. package/dist/theme/slot-recipes/index.d.ts +2 -158
  82. package/dist/theme/slot-recipes/index.js +2 -4
  83. package/dist/theme/slot-recipes/index.js.map +1 -1
  84. package/dist/theme/themeUtils.d.ts +6 -0
  85. package/dist/theme/themeUtils.js +7 -1
  86. package/dist/theme/themeUtils.js.map +1 -1
  87. package/dist/utilities/BitkitPortalContext.js +2 -3
  88. package/dist/utilities/BitkitPortalContext.js.map +1 -1
  89. package/docs/v1-to-v2-migration-guide.md +1 -48
  90. package/package.json +1 -1
  91. package/dist/components/BitkitFilter/BitkitFilter.context.d.ts +0 -65
  92. package/dist/components/BitkitFilter/BitkitFilter.context.js +0 -82
  93. package/dist/components/BitkitFilter/BitkitFilter.context.js.map +0 -1
  94. package/dist/components/BitkitFilter/BitkitFilter.d.ts +0 -55
  95. package/dist/components/BitkitFilter/BitkitFilter.js +0 -247
  96. package/dist/components/BitkitFilter/BitkitFilter.js.map +0 -1
  97. package/dist/components/BitkitFilter/BitkitFilter.utils.d.ts +0 -18
  98. package/dist/components/BitkitFilter/BitkitFilter.utils.js +0 -42
  99. package/dist/components/BitkitFilter/BitkitFilter.utils.js.map +0 -1
  100. package/dist/components/BitkitFilter/BitkitFilterAdd.d.ts +0 -18
  101. package/dist/components/BitkitFilter/BitkitFilterAdd.js +0 -200
  102. package/dist/components/BitkitFilter/BitkitFilterAdd.js.map +0 -1
  103. package/dist/components/BitkitFilter/BitkitFilterDateRange.d.ts +0 -26
  104. package/dist/components/BitkitFilter/BitkitFilterDateRange.js +0 -118
  105. package/dist/components/BitkitFilter/BitkitFilterDateRange.js.map +0 -1
  106. package/dist/components/BitkitFilter/BitkitFilterSearch.d.ts +0 -23
  107. package/dist/components/BitkitFilter/BitkitFilterSearch.js +0 -72
  108. package/dist/components/BitkitFilter/BitkitFilterSearch.js.map +0 -1
  109. package/dist/components/BitkitFilter/BitkitFilterSelect.d.ts +0 -61
  110. package/dist/components/BitkitFilter/BitkitFilterSelect.js +0 -149
  111. package/dist/components/BitkitFilter/BitkitFilterSelect.js.map +0 -1
  112. package/dist/components/BitkitFilter/BitkitFilterSwitch.d.ts +0 -28
  113. package/dist/components/BitkitFilter/BitkitFilterSwitch.js +0 -87
  114. package/dist/components/BitkitFilter/BitkitFilterSwitch.js.map +0 -1
  115. package/dist/components/BitkitFilter/components/FilterChip.d.ts +0 -23
  116. package/dist/components/BitkitFilter/components/FilterChip.js +0 -66
  117. package/dist/components/BitkitFilter/components/FilterChip.js.map +0 -1
  118. package/dist/components/BitkitFilter/components/FilterField.d.ts +0 -15
  119. package/dist/components/BitkitFilter/components/FilterField.js +0 -60
  120. package/dist/components/BitkitFilter/components/FilterField.js.map +0 -1
  121. package/dist/components/BitkitFilter/components/FilterPanel.d.ts +0 -42
  122. package/dist/components/BitkitFilter/components/FilterPanel.js +0 -126
  123. package/dist/components/BitkitFilter/components/FilterPanel.js.map +0 -1
  124. package/dist/components/BitkitFilter/components/FilterSearchInput.d.ts +0 -15
  125. package/dist/components/BitkitFilter/components/FilterSearchInput.js +0 -41
  126. package/dist/components/BitkitFilter/components/FilterSearchInput.js.map +0 -1
  127. package/dist/components/BitkitFilter/components/FilterSelectForm.d.ts +0 -45
  128. package/dist/components/BitkitFilter/components/FilterSelectForm.js +0 -327
  129. package/dist/components/BitkitFilter/components/FilterSelectForm.js.map +0 -1
  130. package/dist/theme/recipes/index.d.ts +0 -525
  131. package/dist/theme/slot-recipes/Filter.recipe.d.ts +0 -37
  132. package/dist/theme/slot-recipes/Filter.recipe.js +0 -649
  133. package/dist/theme/slot-recipes/Filter.recipe.js.map +0 -1
  134. package/dist/theme/slot-recipes/Listbox.recipe.d.ts +0 -22
  135. package/dist/theme/slot-recipes/Listbox.recipe.js +0 -92
  136. package/dist/theme/slot-recipes/Listbox.recipe.js.map +0 -1
@@ -1,18 +0,0 @@
1
- import { ReactNode } from 'react';
2
- export interface BitkitFilterAddProps {
3
- /**
4
- * `BitkitFilter.Select` elements, also inside fragments or your own components. Each is listed in
5
- * the menu, in the order they mount, until it holds a value.
6
- */
7
- children: ReactNode;
8
- }
9
- /**
10
- * Optional filters behind an "Add filter" button. A filter picked from its menu opens its popover
11
- * there; once applied it shows as a removable chip, and leaves the menu until it is removed. On
12
- * mobile the menu is a sheet over the filters dialog.
13
- */
14
- declare const BitkitFilterAdd: {
15
- ({ children }: BitkitFilterAddProps): import('react').JSX.Element;
16
- displayName: string;
17
- };
18
- export default BitkitFilterAdd;
@@ -1,200 +0,0 @@
1
- import IconChevronRight from "../../icons/IconChevronRight.js";
2
- import IconInfoCircle from "../../icons/IconInfoCircle.js";
3
- import IconPlus from "../../icons/IconPlus.js";
4
- import { usePortalContext } from "../../utilities/BitkitPortalContext.js";
5
- import BitkitButton from "../BitkitButton/BitkitButton.js";
6
- import BitkitTooltip from "../BitkitTooltip/BitkitTooltip.js";
7
- import { FilterAddContextProvider, useFilterContext } from "./BitkitFilter.context.js";
8
- import { Box } from "@chakra-ui/react/box";
9
- import { chakra } from "@chakra-ui/react/styled-system";
10
- import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
11
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
- import { Portal } from "@chakra-ui/react/portal";
13
- import { Menu } from "@chakra-ui/react/menu";
14
- import { Text } from "@chakra-ui/react/text";
15
- import { Dialog } from "@chakra-ui/react/dialog";
16
- //#region lib/components/BitkitFilter/BitkitFilterAdd.tsx
17
- /**
18
- * Optional filters behind an "Add filter" button. A filter picked from its menu opens its popover
19
- * there; once applied it shows as a removable chip, and leaves the menu until it is removed. On
20
- * mobile the menu is a sheet over the filters dialog.
21
- */
22
- var BitkitFilterAdd = ({ children }) => {
23
- const triggerId = useId();
24
- const { isDisabled, isMobile, styles } = useFilterContext();
25
- const { disablePortal } = usePortalContext();
26
- const [isSheetOpen, setIsSheetOpen] = useState(false);
27
- const [addingId, setAddingId] = useState();
28
- const [highlightedId, setHighlightedId] = useState(null);
29
- const [entries, setEntries] = useState(/* @__PURE__ */ new Map());
30
- const register = useCallback((id, entry) => {
31
- setEntries((prev) => new Map(prev).set(id, entry));
32
- }, []);
33
- const unregister = useCallback((id) => {
34
- setEntries((prev) => {
35
- const next = new Map(prev);
36
- next.delete(id);
37
- return next;
38
- });
39
- }, []);
40
- const getTrigger = useCallback(() => document.getElementById(triggerId), [triggerId]);
41
- const stopAdding = useCallback(() => setAddingId(void 0), []);
42
- const available = [...entries].filter(([, entry]) => entry.isEmpty);
43
- const isEmpty = !available.length;
44
- const focusPendingFrom = useRef(null);
45
- const focusTrigger = useCallback(() => {
46
- const trigger = getTrigger();
47
- if (trigger instanceof HTMLButtonElement && !trigger.disabled) {
48
- trigger.focus();
49
- return;
50
- }
51
- const from = document.activeElement;
52
- focusPendingFrom.current = from;
53
- document.addEventListener("focusin", () => {
54
- if (focusPendingFrom.current === from) focusPendingFrom.current = null;
55
- }, { once: true });
56
- }, [getTrigger]);
57
- useEffect(() => {
58
- const from = focusPendingFrom.current;
59
- if (!from || isEmpty) return;
60
- focusPendingFrom.current = null;
61
- const active = document.activeElement;
62
- if (active === from || active === document.body) getTrigger()?.focus();
63
- }, [getTrigger, isEmpty]);
64
- const context = useMemo(() => ({
65
- addingId,
66
- focusTrigger,
67
- getTrigger,
68
- register,
69
- stopAdding,
70
- unregister
71
- }), [
72
- addingId,
73
- focusTrigger,
74
- getTrigger,
75
- register,
76
- stopAdding,
77
- unregister
78
- ]);
79
- const isDisabledEntry = (entry) => !entry.disabledReason && !entry.hasOptions;
80
- const pick = (id) => {
81
- if (entries.get(id)?.disabledReason) return;
82
- setAddingId(id);
83
- };
84
- const addButton = /* @__PURE__ */ jsx(BitkitButton, {
85
- alignSelf: "flex-start",
86
- "aria-disabled": isDisabled || void 0,
87
- "data-disabled": isDisabled ? "" : void 0,
88
- icon: IconPlus,
89
- id: isMobile ? triggerId : void 0,
90
- onClick: isMobile ? () => !isDisabled && setIsSheetOpen(true) : void 0,
91
- onKeyDownCapture: isDisabled ? (event) => {
92
- if ([
93
- "ArrowDown",
94
- "ArrowUp",
95
- "Enter",
96
- " "
97
- ].includes(event.key)) event.preventDefault();
98
- } : void 0,
99
- size: isMobile ? "md" : "sm",
100
- state: isEmpty ? "disabled" : void 0,
101
- variant: "tertiary",
102
- children: "Add filter"
103
- });
104
- return /* @__PURE__ */ jsxs(FilterAddContextProvider, {
105
- value: context,
106
- children: [children, isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [addButton, /* @__PURE__ */ jsx(Dialog.Root, {
107
- onOpenChange: ({ open }) => setIsSheetOpen(open),
108
- open: isSheetOpen,
109
- unstyled: true,
110
- children: /* @__PURE__ */ jsxs(Portal, {
111
- disabled: disablePortal,
112
- children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { css: styles.addSheetBackdrop }), /* @__PURE__ */ jsx(Dialog.Positioner, {
113
- css: styles.addSheetPositioner,
114
- children: /* @__PURE__ */ jsxs(Dialog.Content, {
115
- css: styles.addSheet,
116
- children: [/* @__PURE__ */ jsx(Dialog.Title, {
117
- css: styles.addMenuLabel,
118
- children: "Select filter"
119
- }), available.map(([id, entry]) => /* @__PURE__ */ jsxs(chakra.button, {
120
- "aria-disabled": entry.disabledReason ? true : void 0,
121
- css: styles.addSheetItem,
122
- "data-not-applicable": entry.disabledReason ? "" : void 0,
123
- disabled: isDisabledEntry(entry),
124
- onClick: () => {
125
- if (entry.disabledReason) return;
126
- setIsSheetOpen(false);
127
- pick(id);
128
- },
129
- type: "button",
130
- children: [/* @__PURE__ */ jsxs(Box, {
131
- as: "span",
132
- flex: "1",
133
- children: [/* @__PURE__ */ jsx(Text, {
134
- as: "span",
135
- display: "block",
136
- children: entry.label
137
- }), !!entry.disabledReason && /* @__PURE__ */ jsx(Text, {
138
- as: "span",
139
- css: styles.addSheetItemReason,
140
- display: "block",
141
- children: entry.disabledReason
142
- })]
143
- }), /* @__PURE__ */ jsx(IconChevronRight, { css: styles.addMenuIcon })]
144
- }, id))]
145
- })
146
- })]
147
- })
148
- })] }) : /* @__PURE__ */ jsxs(Menu.Root, {
149
- ids: { trigger: triggerId },
150
- onHighlightChange: ({ highlightedValue }) => setHighlightedId(highlightedValue),
151
- onOpenChange: ({ open }) => {
152
- if (!open) setHighlightedId(null);
153
- },
154
- onSelect: ({ value }) => pick(value),
155
- unstyled: true,
156
- children: [/* @__PURE__ */ jsx(Menu.Trigger, {
157
- asChild: true,
158
- children: addButton
159
- }), /* @__PURE__ */ jsx(Portal, {
160
- disabled: disablePortal,
161
- children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsx(Menu.Content, {
162
- css: styles.addMenu,
163
- children: available.map(([id, entry]) => /* @__PURE__ */ jsxs(Menu.Item, {
164
- "aria-disabled": entry.disabledReason ? true : void 0,
165
- closeOnSelect: !entry.disabledReason,
166
- css: styles.addMenuItem,
167
- "data-not-applicable": entry.disabledReason ? "" : void 0,
168
- disabled: isDisabledEntry(entry),
169
- value: id,
170
- children: [/* @__PURE__ */ jsxs(Text, {
171
- flex: "1",
172
- children: [entry.label, !!entry.disabledReason && /* @__PURE__ */ jsx(Text, {
173
- as: "span",
174
- srOnly: true,
175
- children: `, ${entry.disabledReason}`
176
- })]
177
- }), entry.disabledReason ? /* @__PURE__ */ jsx(BitkitTooltip, {
178
- open: highlightedId === id,
179
- placement: "right",
180
- text: entry.disabledReason,
181
- children: /* @__PURE__ */ jsx(IconInfoCircle, {
182
- css: styles.addMenuIcon,
183
- size: "16"
184
- })
185
- }) : /* @__PURE__ */ jsx(IconChevronRight, {
186
- css: styles.addMenuIcon,
187
- "data-add-chevron": true,
188
- size: "16"
189
- })]
190
- }, id))
191
- }) })
192
- })]
193
- })]
194
- });
195
- };
196
- BitkitFilterAdd.displayName = "BitkitFilterAdd";
197
- //#endregion
198
- export { BitkitFilterAdd as default };
199
-
200
- //# sourceMappingURL=BitkitFilterAdd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BitkitFilterAdd.js","names":["_Fragment"],"sources":["../../../lib/components/BitkitFilter/BitkitFilterAdd.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { Dialog } from '@chakra-ui/react/dialog';\nimport { Menu } from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\n// `chakra.button`: the mobile sheet's rows are bare buttons styled by the filter recipe.\nimport { chakra } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { type KeyboardEvent, type ReactNode, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { IconChevronRight, IconInfoCircle, IconPlus } from '../../icons';\nimport { usePortalContext } from '../../utilities/BitkitPortalContext';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport BitkitTooltip from '../BitkitTooltip/BitkitTooltip';\nimport { FilterAddContextProvider, type FilterAddEntry, useFilterContext } from './BitkitFilter.context';\n\nexport interface BitkitFilterAddProps {\n /**\n * `BitkitFilter.Select` elements, also inside fragments or your own components. Each is listed in\n * the menu, in the order they mount, until it holds a value.\n */\n children: ReactNode;\n}\n\n/**\n * Optional filters behind an \"Add filter\" button. A filter picked from its menu opens its popover\n * there; once applied it shows as a removable chip, and leaves the menu until it is removed. On\n * mobile the menu is a sheet over the filters dialog.\n */\nconst BitkitFilterAdd = ({ children }: BitkitFilterAddProps) => {\n // The popovers anchor to the button by id: a ref on a button inside Ark's `asChild` trigger trips React 18.\n const triggerId = useId();\n const { isDisabled, isMobile, styles } = useFilterContext();\n const { disablePortal } = usePortalContext();\n const [isSheetOpen, setIsSheetOpen] = useState(false);\n const [addingId, setAddingId] = useState<string>();\n const [highlightedId, setHighlightedId] = useState<string | null>(null);\n const [entries, setEntries] = useState<ReadonlyMap<string, FilterAddEntry>>(new Map());\n\n const register = useCallback((id: string, entry: FilterAddEntry) => {\n // `set` on a known id keeps its place, so an entry doesn't move when its props change.\n setEntries((prev) => new Map(prev).set(id, entry));\n }, []);\n\n const unregister = useCallback((id: string) => {\n setEntries((prev) => {\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n const getTrigger = useCallback(() => document.getElementById(triggerId), [triggerId]);\n const stopAdding = useCallback(() => setAddingId(undefined), []);\n\n const available = [...entries].filter(([, entry]) => entry.isEmpty);\n const isEmpty = !available.length;\n\n // The button is disabled while every filter is applied, so focus waits until a removal re-enables it.\n // It only moves if it hasn't gone anywhere since: still on the removed control, or dropped to the page.\n // Focus landing anywhere meanwhile (which dropping to the page doesn't count as) calls it off.\n const focusPendingFrom = useRef<Element | null>(null);\n const focusTrigger = useCallback(() => {\n const trigger = getTrigger();\n if (trigger instanceof HTMLButtonElement && !trigger.disabled) {\n trigger.focus();\n return;\n }\n const from = document.activeElement;\n focusPendingFrom.current = from;\n document.addEventListener(\n 'focusin',\n () => {\n if (focusPendingFrom.current === from) focusPendingFrom.current = null;\n },\n { once: true },\n );\n }, [getTrigger]);\n useEffect(() => {\n const from = focusPendingFrom.current;\n if (!from || isEmpty) return;\n focusPendingFrom.current = null;\n const active = document.activeElement;\n if (active === from || active === document.body) getTrigger()?.focus();\n }, [getTrigger, isEmpty]);\n\n const context = useMemo(\n () => ({ addingId, focusTrigger, getTrigger, register, stopAdding, unregister }),\n [addingId, focusTrigger, getTrigger, register, stopAdding, unregister],\n );\n\n // A filter with no options to pick is plainly disabled. One with a `disabledReason` stays reachable,\n // so keyboard and screen-reader users can learn the reason too, but can't be picked.\n const isDisabledEntry = (entry: FilterAddEntry) => !entry.disabledReason && !entry.hasOptions;\n const pick = (id: string) => {\n if (entries.get(id)?.disabledReason) return;\n setAddingId(id);\n };\n\n // While the page loads the button only looks disabled (`aria-disabled`), so it keeps a focus handed to it.\n // `data-disabled` keeps the menu from opening on click, and the keys that open it are refused here.\n const addButton = (\n <BitkitButton\n alignSelf=\"flex-start\"\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? '' : undefined}\n icon={IconPlus}\n id={isMobile ? triggerId : undefined}\n onClick={isMobile ? () => !isDisabled && setIsSheetOpen(true) : undefined}\n onKeyDownCapture={\n isDisabled\n ? (event: KeyboardEvent) => {\n if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) event.preventDefault();\n }\n : undefined\n }\n size={isMobile ? 'md' : 'sm'}\n state={isEmpty ? 'disabled' : undefined}\n variant=\"tertiary\"\n >\n Add filter\n </BitkitButton>\n );\n\n return (\n <FilterAddContextProvider value={context}>\n {children}\n {isMobile ? (\n <>\n {addButton}\n <Dialog.Root onOpenChange={({ open }) => setIsSheetOpen(open)} open={isSheetOpen} unstyled>\n <Portal disabled={disablePortal}>\n <Dialog.Backdrop css={styles.addSheetBackdrop} />\n <Dialog.Positioner css={styles.addSheetPositioner}>\n <Dialog.Content css={styles.addSheet}>\n <Dialog.Title css={styles.addMenuLabel}>Select filter</Dialog.Title>\n {available.map(([id, entry]) => (\n <chakra.button\n aria-disabled={entry.disabledReason ? true : undefined}\n css={styles.addSheetItem}\n data-not-applicable={entry.disabledReason ? '' : undefined}\n disabled={isDisabledEntry(entry)}\n key={id}\n onClick={() => {\n if (entry.disabledReason) return;\n setIsSheetOpen(false);\n pick(id);\n }}\n type=\"button\"\n >\n <Box as=\"span\" flex=\"1\">\n <Text as=\"span\" display=\"block\">\n {entry.label}\n </Text>\n {/* A touch screen has no hover to open a tooltip, so the reason is spelled out. */}\n {!!entry.disabledReason && (\n <Text as=\"span\" css={styles.addSheetItemReason} display=\"block\">\n {entry.disabledReason}\n </Text>\n )}\n </Box>\n <IconChevronRight css={styles.addMenuIcon} />\n </chakra.button>\n ))}\n </Dialog.Content>\n </Dialog.Positioner>\n </Portal>\n </Dialog.Root>\n </>\n ) : (\n <Menu.Root\n ids={{ trigger: triggerId }}\n onHighlightChange={({ highlightedValue }) => setHighlightedId(highlightedValue)}\n onOpenChange={({ open }) => {\n if (!open) setHighlightedId(null);\n }}\n onSelect={({ value }) => pick(value)}\n unstyled\n >\n <Menu.Trigger asChild>{addButton}</Menu.Trigger>\n <Portal disabled={disablePortal}>\n <Menu.Positioner>\n <Menu.Content css={styles.addMenu}>\n {available.map(([id, entry]) => (\n <Menu.Item\n aria-disabled={entry.disabledReason ? true : undefined}\n closeOnSelect={!entry.disabledReason}\n css={styles.addMenuItem}\n data-not-applicable={entry.disabledReason ? '' : undefined}\n disabled={isDisabledEntry(entry)}\n key={id}\n value={id}\n >\n <Text flex=\"1\">\n {entry.label}\n {!!entry.disabledReason && <Text as=\"span\" srOnly>{`, ${entry.disabledReason}`}</Text>}\n </Text>\n {entry.disabledReason ? (\n // On the icon rather than the row: as the row's trigger, the tooltip would replace\n // the id its `aria-activedescendant` points at. It opens while the row is highlighted,\n // by pointer or arrow keys, since the menu keeps focus on itself.\n <BitkitTooltip open={highlightedId === id} placement=\"right\" text={entry.disabledReason}>\n <IconInfoCircle css={styles.addMenuIcon} size=\"16\" />\n </BitkitTooltip>\n ) : (\n <IconChevronRight css={styles.addMenuIcon} data-add-chevron size=\"16\" />\n )}\n </Menu.Item>\n ))}\n </Menu.Content>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n )}\n </FilterAddContextProvider>\n );\n};\n\nBitkitFilterAdd.displayName = 'BitkitFilterAdd';\n\nexport default BitkitFilterAdd;\n"],"mappings":"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"}
@@ -1,26 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- import { BitkitCalendarProps } from '../BitkitCalendar/BitkitCalendar';
3
- export type BitkitFilterDateRangeValue = [start: Date, end: Date] | null;
4
- export interface BitkitFilterDateRangeProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {
5
- /** Says why a day can't be picked, e.g. "Can't select a date in the future". Shown on hover. */
6
- dayTooltip?: BitkitCalendarProps['dayTooltip'];
7
- /** Chip text while no range is applied. Defaults to "All dates". */
8
- emptyLabel?: string;
9
- /** Name of the filter, shown on mobile as the field label and the title of its view. Defaults to "Date". */
10
- label?: string;
11
- /** Latest selectable day. Defaults to today. */
12
- max?: Date;
13
- /** Earliest selectable day. Defaults to two years before today. */
14
- min?: Date;
15
- /**
16
- * Called on "Apply" and "Clear". An applied range is `[start, end]`, where `start` is the first
17
- * day's midnight and `end` the last day's final millisecond, so the range covers both days whole.
18
- */
19
- onValueChange: (value: BitkitFilterDateRangeValue) => void;
20
- /** The value "Clear filters" restores. Defaults to no range. */
21
- resetValue?: BitkitFilterDateRangeValue;
22
- value: BitkitFilterDateRangeValue;
23
- }
24
- /** A filter for a date range, picked on a calendar and applied with "Apply". */
25
- declare const BitkitFilterDateRange: import('react').ForwardRefExoticComponent<BitkitFilterDateRangeProps & import('react').RefAttributes<HTMLButtonElement>>;
26
- export default BitkitFilterDateRange;
@@ -1,118 +0,0 @@
1
- import IconCalendar from "../../icons/IconCalendar.js";
2
- import BitkitButton from "../BitkitButton/BitkitButton.js";
3
- import BitkitCalendar from "../BitkitCalendar/BitkitCalendar.js";
4
- import { endOfDay, formatDateRange, isEqualFilterValue } from "./BitkitFilter.utils.js";
5
- import { useFilterContext, useFilterRegistration } from "./BitkitFilter.context.js";
6
- import FilterChip from "./components/FilterChip.js";
7
- import FilterField from "./components/FilterField.js";
8
- import FilterPanel, { FilterPanelFooter, FilterPanelHeader } from "./components/FilterPanel.js";
9
- import { Box } from "@chakra-ui/react/box";
10
- import { cloneElement, forwardRef, useState } from "react";
11
- import { jsx, jsxs } from "react/jsx-runtime";
12
- //#region lib/components/BitkitFilter/BitkitFilterDateRange.tsx
13
- var today = () => /* @__PURE__ */ new Date();
14
- var twoYearsAgo = () => {
15
- const date = /* @__PURE__ */ new Date();
16
- date.setFullYear(date.getFullYear() - 2);
17
- return date;
18
- };
19
- /** A filter for a date range, picked on a calendar and applied with "Apply". */
20
- var BitkitFilterDateRange = forwardRef((props, ref) => {
21
- const { dayTooltip, emptyLabel = "All dates", label = "Date", max, min, onValueChange, resetValue = null, value, ...rest } = props;
22
- const { isDisabled, isMobile, styles } = useFilterContext();
23
- const [open, setOpen] = useState(false);
24
- const [draft, setDraft] = useState(value);
25
- useFilterRegistration(value, resetValue, onValueChange);
26
- const onOpenChange = (isOpen) => {
27
- if (isOpen && isDisabled) return;
28
- setOpen(isOpen);
29
- if (isOpen) setDraft(value);
30
- };
31
- const apply = (next) => {
32
- onValueChange(next);
33
- setOpen(false);
34
- };
35
- const draftRange = draft?.length === 2 ? [draft[0], endOfDay(draft[1])] : null;
36
- const isApplyDisabled = !draftRange || isEqualFilterValue(draftRange, value);
37
- const valueText = value ? formatDateRange(value) : emptyLabel;
38
- if (isMobile) return /* @__PURE__ */ jsxs(FilterPanel, {
39
- onOpenChange,
40
- open,
41
- trigger: /* @__PURE__ */ jsx(FilterField, {
42
- ...rest,
43
- icon: IconCalendar,
44
- isOpen: open,
45
- label,
46
- onClick: () => onOpenChange(true),
47
- ref,
48
- value: valueText
49
- }),
50
- children: [
51
- /* @__PURE__ */ jsx(FilterPanelHeader, { title: label }),
52
- /* @__PURE__ */ jsx(Box, {
53
- flex: "1",
54
- overflowY: "auto",
55
- children: /* @__PURE__ */ jsx(BitkitCalendar, {
56
- dayTooltip,
57
- device: "mobile",
58
- layout: "1-month",
59
- max: max ?? today(),
60
- min: min ?? twoYearsAgo(),
61
- onValueChange: setDraft,
62
- showOutsideDays: true,
63
- showSelectedDate: true,
64
- value: draft
65
- })
66
- }),
67
- /* @__PURE__ */ jsx(FilterPanelFooter, {
68
- isApplyDisabled,
69
- onApply: () => apply(draftRange),
70
- start: value ? {
71
- label: "Reset",
72
- onClick: () => apply(null)
73
- } : void 0
74
- })
75
- ]
76
- });
77
- return /* @__PURE__ */ jsx(FilterChip, {
78
- icon: IconCalendar,
79
- ref,
80
- renderTrigger: (button) => /* @__PURE__ */ jsx(BitkitCalendar, {
81
- dayTooltip,
82
- footer: /* @__PURE__ */ jsxs(Box, {
83
- css: styles.calendarFooter,
84
- children: [/* @__PURE__ */ jsx(Box, {
85
- flex: "1",
86
- children: !!value && /* @__PURE__ */ jsx(BitkitButton, {
87
- onClick: () => apply(null),
88
- size: "sm",
89
- variant: "tertiary",
90
- children: "Clear"
91
- })
92
- }), /* @__PURE__ */ jsx(BitkitButton, {
93
- onClick: () => apply(draftRange),
94
- size: "sm",
95
- state: isApplyDisabled ? "disabled" : void 0,
96
- children: "Apply"
97
- })]
98
- }),
99
- layout: "1-month",
100
- max: max ?? today(),
101
- min: min ?? twoYearsAgo(),
102
- onOpenChange,
103
- onValueChange: setDraft,
104
- open,
105
- showOutsideDays: true,
106
- showSelectedDate: true,
107
- value: draft,
108
- children: cloneElement(button, { "aria-label": valueText })
109
- }),
110
- value: valueText,
111
- ...rest
112
- });
113
- });
114
- BitkitFilterDateRange.displayName = "BitkitFilterDateRange";
115
- //#endregion
116
- export { BitkitFilterDateRange as default };
117
-
118
- //# sourceMappingURL=BitkitFilterDateRange.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BitkitFilterDateRange.js","names":[],"sources":["../../../lib/components/BitkitFilter/BitkitFilterDateRange.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { cloneElement, forwardRef, useState } from 'react';\n\nimport { IconCalendar } from '../../icons';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport BitkitCalendar, { type BitkitCalendarProps } from '../BitkitCalendar/BitkitCalendar';\nimport { useFilterContext, useFilterRegistration } from './BitkitFilter.context';\nimport { endOfDay, formatDateRange, isEqualFilterValue } from './BitkitFilter.utils';\nimport FilterChip from './components/FilterChip';\nimport FilterField from './components/FilterField';\nimport FilterPanel, { FilterPanelFooter, FilterPanelHeader } from './components/FilterPanel';\n\nexport type BitkitFilterDateRangeValue = [start: Date, end: Date] | null;\n\nexport interface BitkitFilterDateRangeProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {\n /** Says why a day can't be picked, e.g. \"Can't select a date in the future\". Shown on hover. */\n dayTooltip?: BitkitCalendarProps['dayTooltip'];\n /** Chip text while no range is applied. Defaults to \"All dates\". */\n emptyLabel?: string;\n /** Name of the filter, shown on mobile as the field label and the title of its view. Defaults to \"Date\". */\n label?: string;\n /** Latest selectable day. Defaults to today. */\n max?: Date;\n /** Earliest selectable day. Defaults to two years before today. */\n min?: Date;\n /**\n * Called on \"Apply\" and \"Clear\". An applied range is `[start, end]`, where `start` is the first\n * day's midnight and `end` the last day's final millisecond, so the range covers both days whole.\n */\n onValueChange: (value: BitkitFilterDateRangeValue) => void;\n /** The value \"Clear filters\" restores. Defaults to no range. */\n resetValue?: BitkitFilterDateRangeValue;\n value: BitkitFilterDateRangeValue;\n}\n\nconst today = () => new Date();\n\nconst twoYearsAgo = () => {\n const date = new Date();\n date.setFullYear(date.getFullYear() - 2);\n return date;\n};\n\n/** A filter for a date range, picked on a calendar and applied with \"Apply\". */\n// The ref lands on the chip's (or on mobile the field's) button; other props on its wrapper.\nconst BitkitFilterDateRange = forwardRef<HTMLButtonElement, BitkitFilterDateRangeProps>((props, ref) => {\n const {\n dayTooltip,\n emptyLabel = 'All dates',\n label = 'Date',\n max,\n min,\n onValueChange,\n resetValue = null,\n value,\n ...rest\n } = props;\n const { isDisabled, isMobile, styles } = useFilterContext();\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState<Date[] | null>(value);\n\n useFilterRegistration(value, resetValue, onValueChange);\n\n const onOpenChange = (isOpen: boolean) => {\n // The chip is only `aria-disabled` while the page loads, so the calendar refuses to open here.\n if (isOpen && isDisabled) return;\n setOpen(isOpen);\n if (isOpen) setDraft(value);\n };\n\n const apply = (next: BitkitFilterDateRangeValue) => {\n onValueChange(next);\n setOpen(false);\n };\n\n const draftRange: BitkitFilterDateRangeValue = draft?.length === 2 ? [draft[0], endOfDay(draft[1])] : null;\n const isApplyDisabled = !draftRange || isEqualFilterValue(draftRange, value);\n const valueText = value ? formatDateRange(value) : emptyLabel;\n\n if (isMobile) {\n return (\n <FilterPanel\n onOpenChange={onOpenChange}\n open={open}\n trigger={\n <FilterField\n {...rest}\n icon={IconCalendar}\n isOpen={open}\n label={label}\n onClick={() => onOpenChange(true)}\n ref={ref}\n value={valueText}\n />\n }\n >\n <FilterPanelHeader title={label} />\n <Box flex=\"1\" overflowY=\"auto\">\n <BitkitCalendar\n dayTooltip={dayTooltip}\n device=\"mobile\"\n layout=\"1-month\"\n max={max ?? today()}\n min={min ?? twoYearsAgo()}\n onValueChange={setDraft}\n showOutsideDays\n showSelectedDate\n value={draft}\n />\n </Box>\n <FilterPanelFooter\n isApplyDisabled={isApplyDisabled}\n onApply={() => apply(draftRange)}\n start={value ? { label: 'Reset', onClick: () => apply(null) } : undefined}\n />\n </FilterPanel>\n );\n }\n\n return (\n <FilterChip\n icon={IconCalendar}\n ref={ref}\n renderTrigger={(button) => (\n <BitkitCalendar\n dayTooltip={dayTooltip}\n footer={\n <Box css={styles.calendarFooter}>\n <Box flex=\"1\">\n {!!value && (\n <BitkitButton onClick={() => apply(null)} size=\"sm\" variant=\"tertiary\">\n Clear\n </BitkitButton>\n )}\n </Box>\n <BitkitButton\n onClick={() => apply(draftRange)}\n size=\"sm\"\n state={isApplyDisabled ? 'disabled' : undefined}\n >\n Apply\n </BitkitButton>\n </Box>\n }\n layout=\"1-month\"\n max={max ?? today()}\n min={min ?? twoYearsAgo()}\n onOpenChange={onOpenChange}\n onValueChange={setDraft}\n open={open}\n showOutsideDays\n showSelectedDate\n value={draft}\n >\n {/* Zag names the trigger \"Open calendar\"; the chip is named by the text it shows instead. */}\n {cloneElement(button, { 'aria-label': valueText })}\n </BitkitCalendar>\n )}\n value={valueText}\n {...rest}\n />\n );\n});\n\nBitkitFilterDateRange.displayName = 'BitkitFilterDateRange';\n\nexport default BitkitFilterDateRange;\n"],"mappings":";;;;;;;;;;;;AAmCA,IAAM,8BAAc,IAAI,KAAK;AAE7B,IAAM,oBAAoB;CACxB,MAAM,uBAAO,IAAI,KAAK;CACtB,KAAK,YAAY,KAAK,YAAY,IAAI,CAAC;CACvC,OAAO;AACT;;AAIA,IAAM,wBAAwB,YAA2D,OAAO,QAAQ;CACtG,MAAM,EACJ,YACA,aAAa,aACb,QAAQ,QACR,KACA,KACA,eACA,aAAa,MACb,OACA,GAAG,SACD;CACJ,MAAM,EAAE,YAAY,UAAU,WAAW,iBAAiB;CAC1D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CAEvD,sBAAsB,OAAO,YAAY,aAAa;CAEtD,MAAM,gBAAgB,WAAoB;EAExC,IAAI,UAAU,YAAY;EAC1B,QAAQ,MAAM;EACd,IAAI,QAAQ,SAAS,KAAK;CAC5B;CAEA,MAAM,SAAS,SAAqC;EAClD,cAAc,IAAI;EAClB,QAAQ,KAAK;CACf;CAEA,MAAM,aAAyC,OAAO,WAAW,IAAI,CAAC,MAAM,IAAI,SAAS,MAAM,EAAE,CAAC,IAAI;CACtG,MAAM,kBAAkB,CAAC,cAAc,mBAAmB,YAAY,KAAK;CAC3E,MAAM,YAAY,QAAQ,gBAAgB,KAAK,IAAI;CAEnD,IAAI,UACF,OACE,qBAAC,aAAD;EACgB;EACR;EACN,SACE,oBAAC,aAAD;GACE,GAAI;GACJ,MAAM;GACN,QAAQ;GACD;GACP,eAAe,aAAa,IAAI;GAC3B;GACL,OAAO;EACR,CAAA;EAZL,UAAA;GAeE,oBAAC,mBAAD,EAAmB,OAAO,MAAQ,CAAA;GAClC,oBAAC,KAAD;IAAK,MAAK;IAAI,WAAU;IACtB,UAAA,oBAAC,gBAAD;KACc;KACZ,QAAO;KACP,QAAO;KACP,KAAK,OAAO,MAAM;KAClB,KAAK,OAAO,YAAY;KACxB,eAAe;KACf,iBAAA;KACA,kBAAA;KACA,OAAO;IACR,CAAA;GACE,CAAA;GACL,oBAAC,mBAAD;IACmB;IACjB,eAAe,MAAM,UAAU;IAC/B,OAAO,QAAQ;KAAE,OAAO;KAAS,eAAe,MAAM,IAAI;IAAE,IAAI,KAAA;GACjE,CAAA;EACU;;CAIjB,OACE,oBAAC,YAAD;EACE,MAAM;EACD;EACL,gBAAgB,WACd,oBAAC,gBAAD;GACc;GACZ,QACE,qBAAC,KAAD;IAAK,KAAK,OAAO;IAAjB,UAAA,CACE,oBAAC,KAAD;KAAK,MAAK;KACP,UAAA,CAAC,CAAC,SACD,oBAAC,cAAD;MAAc,eAAe,MAAM,IAAI;MAAG,MAAK;MAAK,SAAQ;MAAW,UAAA;KAEzD,CAAA;IAEb,CAAA,GACL,oBAAC,cAAD;KACE,eAAe,MAAM,UAAU;KAC/B,MAAK;KACL,OAAO,kBAAkB,aAAa,KAAA;KACvC,UAAA;IAEa,CAAA,CACX;;GAEP,QAAO;GACP,KAAK,OAAO,MAAM;GAClB,KAAK,OAAO,YAAY;GACV;GACd,eAAe;GACT;GACN,iBAAA;GACA,kBAAA;GACA,OAAO;GAGN,UAAA,aAAa,QAAQ,EAAE,cAAc,UAAU,CAAC;EACnC,CAAA;EAElB,OAAO;EACP,GAAI;CACL,CAAA;AAEL,CAAC;AAED,sBAAsB,cAAc"}
@@ -1,23 +0,0 @@
1
- import { BoxProps } from '@chakra-ui/react/box';
2
- export interface BitkitFilterSearchProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {
3
- /** Accessible name of the input. Defaults to "Search". */
4
- label?: string;
5
- /** Called once typing pauses, and right away on clear. */
6
- onValueChange: (value: string) => void;
7
- /** Defaults to "Search...". */
8
- placeholder?: string;
9
- /** The value "Clear filters" restores. Defaults to an empty search. */
10
- resetValue?: string;
11
- /**
12
- * Says what the search matches, in a few words, e.g. "Build number or commit message". Shown on
13
- * hover, but not while typing, and read out with the field.
14
- */
15
- tooltip?: string;
16
- value: string;
17
- }
18
- /**
19
- * Free-text search, shown at the end of the bar whatever its position among the children — on mobile,
20
- * as a full-width row under the bar.
21
- */
22
- declare const BitkitFilterSearch: import('react').ForwardRefExoticComponent<BitkitFilterSearchProps & import('react').RefAttributes<HTMLInputElement>>;
23
- export default BitkitFilterSearch;
@@ -1,72 +0,0 @@
1
- import BitkitLabelTooltip from "../BitkitLabelTooltip/BitkitLabelTooltip.js";
2
- import { useFilterContext, useFilterRegistration } from "./BitkitFilter.context.js";
3
- import FilterSearchInput from "./components/FilterSearchInput.js";
4
- import { forwardRef, useEffect, useRef, useState } from "react";
5
- import { jsx } from "react/jsx-runtime";
6
- //#region lib/components/BitkitFilter/BitkitFilterSearch.tsx
7
- /**
8
- * Free-text search, shown at the end of the bar whatever its position among the children — on mobile,
9
- * as a full-width row under the bar.
10
- */
11
- var BitkitFilterSearch = forwardRef((props, ref) => {
12
- const { label = "Search", onValueChange, placeholder = "Search...", resetValue = "", tooltip, value, ...rest } = props;
13
- const { isMobile } = useFilterContext();
14
- const [text, setText] = useState(value);
15
- const [isFocused, setIsFocused] = useState(false);
16
- const pending = useRef([]);
17
- const valueRef = useRef(value);
18
- valueRef.current = value;
19
- const send = (next) => {
20
- if (next !== valueRef.current) pending.current.push(next);
21
- onValueChange(next);
22
- };
23
- useFilterRegistration(value, resetValue, (next) => {
24
- setText(next);
25
- send(next);
26
- }, false);
27
- useEffect(() => {
28
- const index = pending.current.indexOf(value);
29
- if (index >= 0) {
30
- pending.current.splice(index, 1);
31
- return;
32
- }
33
- pending.current = [];
34
- setText(value);
35
- }, [value]);
36
- useEffect(() => {
37
- if (text === value || !text) return void 0;
38
- const timeout = setTimeout(() => send(text), 300);
39
- return () => clearTimeout(timeout);
40
- }, [text]);
41
- const onTextChange = (next) => {
42
- setText(next);
43
- if (!next) send("");
44
- };
45
- return /* @__PURE__ */ jsx(FilterSearchInput, {
46
- description: tooltip,
47
- label,
48
- onValueChange: onTextChange,
49
- placeholder,
50
- ref,
51
- renderInput: tooltip && !isMobile ? (input) => /* @__PURE__ */ jsx(BitkitLabelTooltip, {
52
- disabled: isFocused,
53
- text: tooltip,
54
- children: input
55
- }) : void 0,
56
- value: text,
57
- ...rest,
58
- onBlur: (event) => {
59
- setIsFocused(false);
60
- rest.onBlur?.(event);
61
- },
62
- onFocus: (event) => {
63
- setIsFocused(true);
64
- rest.onFocus?.(event);
65
- }
66
- });
67
- });
68
- BitkitFilterSearch.displayName = "BitkitFilterSearch";
69
- //#endregion
70
- export { BitkitFilterSearch as default };
71
-
72
- //# sourceMappingURL=BitkitFilterSearch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BitkitFilterSearch.js","names":[],"sources":["../../../lib/components/BitkitFilter/BitkitFilterSearch.tsx"],"sourcesContent":["import { type BoxProps } from '@chakra-ui/react/box';\nimport { forwardRef, useEffect, useRef, useState } from 'react';\n\nimport BitkitLabelTooltip from '../BitkitLabelTooltip/BitkitLabelTooltip';\nimport { useFilterContext, useFilterRegistration } from './BitkitFilter.context';\nimport { SEARCH_DEBOUNCE_MS } from './BitkitFilter.utils';\nimport FilterSearchInput from './components/FilterSearchInput';\n\nexport interface BitkitFilterSearchProps extends Omit<BoxProps, 'children' | 'defaultValue' | 'onChange'> {\n /** Accessible name of the input. Defaults to \"Search\". */\n label?: string;\n /** Called once typing pauses, and right away on clear. */\n onValueChange: (value: string) => void;\n /** Defaults to \"Search...\". */\n placeholder?: string;\n /** The value \"Clear filters\" restores. Defaults to an empty search. */\n resetValue?: string;\n /**\n * Says what the search matches, in a few words, e.g. \"Build number or commit message\". Shown on\n * hover, but not while typing, and read out with the field.\n */\n tooltip?: string;\n value: string;\n}\n\n/**\n * Free-text search, shown at the end of the bar whatever its position among the children — on mobile,\n * as a full-width row under the bar.\n */\nconst BitkitFilterSearch = forwardRef<HTMLInputElement, BitkitFilterSearchProps>((props, ref) => {\n const {\n label = 'Search',\n onValueChange,\n placeholder = 'Search...',\n resetValue = '',\n tooltip,\n value,\n ...rest\n } = props;\n const { isMobile } = useFilterContext();\n const [text, setText] = useState(value);\n // The tooltip stays closed while the field has focus, so it doesn't cover the results being typed for.\n const [isFocused, setIsFocused] = useState(false);\n // What this search sent that hasn't come back as `value` yet. A page may echo a send late, after\n // more has been typed (or sent); such an echo must not overwrite the newer text.\n const pending = useRef<string[]>([]);\n const valueRef = useRef(value);\n valueRef.current = value;\n\n const send = (next: string) => {\n // A send matching `value` changes nothing, so no echo would ever come back to clear it.\n if (next !== valueRef.current) pending.current.push(next);\n onValueChange(next);\n };\n\n useFilterRegistration(\n value,\n resetValue,\n (next: string) => {\n setText(next);\n send(next);\n },\n false,\n );\n\n // Follow outside changes, e.g. a page reset.\n useEffect(() => {\n const index = pending.current.indexOf(value);\n if (index >= 0) {\n // An echo. Only this send has landed: echoes can arrive out of order.\n pending.current.splice(index, 1);\n return;\n }\n pending.current = [];\n setText(value);\n }, [value]);\n\n useEffect(() => {\n // An empty text was already sent right away.\n if (text === value || !text) return undefined;\n const timeout = setTimeout(() => send(text), SEARCH_DEBOUNCE_MS);\n return () => clearTimeout(timeout);\n // `value` is left out on purpose: it changing must not restart a pending debounce.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [text]);\n\n const onTextChange = (next: string) => {\n setText(next);\n // Clearing applies right away rather than after the debounce.\n if (!next) send('');\n };\n\n return (\n <FilterSearchInput\n description={tooltip}\n label={label}\n onValueChange={onTextChange}\n placeholder={placeholder}\n ref={ref}\n // Touch screens have no hover to show a tooltip.\n renderInput={\n tooltip && !isMobile\n ? (input) => (\n <BitkitLabelTooltip disabled={isFocused} text={tooltip}>\n {input}\n </BitkitLabelTooltip>\n )\n : undefined\n }\n value={text}\n {...rest}\n onBlur={(event) => {\n setIsFocused(false);\n rest.onBlur?.(event);\n }}\n onFocus={(event) => {\n setIsFocused(true);\n rest.onFocus?.(event);\n }}\n />\n );\n});\n\nBitkitFilterSearch.displayName = 'BitkitFilterSearch';\n\nexport default BitkitFilterSearch;\n"],"mappings":";;;;;;;;;;AA6BA,IAAM,qBAAqB,YAAuD,OAAO,QAAQ;CAC/F,MAAM,EACJ,QAAQ,UACR,eACA,cAAc,aACd,aAAa,IACb,SACA,OACA,GAAG,SACD;CACJ,MAAM,EAAE,aAAa,iBAAiB;CACtC,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAGhD,MAAM,UAAU,OAAiB,CAAC,CAAC;CACnC,MAAM,WAAW,OAAO,KAAK;CAC7B,SAAS,UAAU;CAEnB,MAAM,QAAQ,SAAiB;EAE7B,IAAI,SAAS,SAAS,SAAS,QAAQ,QAAQ,KAAK,IAAI;EACxD,cAAc,IAAI;CACpB;CAEA,sBACE,OACA,aACC,SAAiB;EAChB,QAAQ,IAAI;EACZ,KAAK,IAAI;CACX,GACA,KACF;CAGA,gBAAgB;EACd,MAAM,QAAQ,QAAQ,QAAQ,QAAQ,KAAK;EAC3C,IAAI,SAAS,GAAG;GAEd,QAAQ,QAAQ,OAAO,OAAO,CAAC;GAC/B;EACF;EACA,QAAQ,UAAU,CAAC;EACnB,QAAQ,KAAK;CACf,GAAG,CAAC,KAAK,CAAC;CAEV,gBAAgB;EAEd,IAAI,SAAS,SAAS,CAAC,MAAM,OAAO,KAAA;EACpC,MAAM,UAAU,iBAAiB,KAAK,IAAI,GAAA,GAAqB;EAC/D,aAAa,aAAa,OAAO;CAGnC,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,gBAAgB,SAAiB;EACrC,QAAQ,IAAI;EAEZ,IAAI,CAAC,MAAM,KAAK,EAAE;CACpB;CAEA,OACE,oBAAC,mBAAD;EACE,aAAa;EACN;EACP,eAAe;EACF;EACR;EAEL,aACE,WAAW,CAAC,YACP,UACC,oBAAC,oBAAD;GAAoB,UAAU;GAAW,MAAM;GAC5C,UAAA;EACiB,CAAA,IAEtB,KAAA;EAEN,OAAO;EACP,GAAI;EACJ,SAAS,UAAU;GACjB,aAAa,KAAK;GAClB,KAAK,SAAS,KAAK;EACrB;EACA,UAAU,UAAU;GAClB,aAAa,IAAI;GACjB,KAAK,UAAU,KAAK;EACtB;CACD,CAAA;AAEL,CAAC;AAED,mBAAmB,cAAc"}
@@ -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;