beez-ui 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +11 -9
- package/dist/components/animated-collapse.js +9 -3
- package/dist/components/animated-list-item.js +37 -34
- package/dist/components/filter-presets-bar.d.ts +71 -0
- package/dist/components/filter-presets-bar.js +508 -0
- package/dist/components/presence-swap.js +38 -51
- package/dist/components/reaction-button.d.ts +7 -2
- package/dist/components/reaction-button.js +59 -48
- package/dist/hooks.d.ts +10 -0
- package/dist/hooks.js +10 -0
- package/dist/index.d.ts +1 -23
- package/dist/index.js +1 -23
- package/dist/styles.css +1 -1
- package/package.json +11 -126
- package/dist/components/bouncing-dots-loader.d.ts +0 -19
- package/dist/components/bouncing-dots-loader.js +0 -47
- package/dist/components/confirm-delete-button.d.ts +0 -29
- package/dist/components/confirm-delete-button.js +0 -254
- package/dist/components/empty-state.d.ts +0 -24
- package/dist/components/empty-state.js +0 -37
- package/dist/components/error-state.d.ts +0 -20
- package/dist/components/error-state.js +0 -145
- package/dist/components/external-browser-handoff.d.ts +0 -27
- package/dist/components/external-browser-handoff.js +0 -306
- package/dist/components/info-popover.d.ts +0 -23
- package/dist/components/info-popover.js +0 -158
- package/dist/components/month-calendar-header.d.ts +0 -65
- package/dist/components/month-calendar-header.js +0 -337
- package/dist/components/month-grid.d.ts +0 -59
- package/dist/components/month-grid.js +0 -301
- package/dist/components/notification-bell.d.ts +0 -50
- package/dist/components/notification-bell.js +0 -338
- package/dist/components/notification-panel.d.ts +0 -56
- package/dist/components/notification-panel.js +0 -281
- package/dist/components/open-in-browser-cta.d.ts +0 -22
- package/dist/components/open-in-browser-cta.js +0 -61
- package/dist/components/pwa-update-control.d.ts +0 -18
- package/dist/components/pwa-update-control.js +0 -119
- package/dist/emoji-picker.d.ts +0 -27
- package/dist/emoji-picker.js +0 -283
- package/dist/hooks/use-minute-clock.d.ts +0 -23
- package/dist/hooks/use-minute-clock.js +0 -147
- package/dist/hooks/use-month-transition-direction.d.ts +0 -21
- package/dist/hooks/use-month-transition-direction.js +0 -110
- package/dist/lib/browser-navigation.d.ts +0 -21
- package/dist/lib/browser-navigation.js +0 -42
- package/dist/lib/in-app-browser.d.ts +0 -35
- package/dist/lib/in-app-browser.js +0 -80
- package/dist/lib/month-grid.d.ts +0 -42
- package/dist/lib/month-grid.js +0 -74
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Saved queries for `FilterQueryBar`: a button that stores the current query under a name and a
|
|
5
|
+
* row of chips to apply, edit or delete them. Persistence stays with the application.
|
|
6
|
+
*/
|
|
7
|
+
import { useId, useState } from "react";
|
|
8
|
+
import { Bookmark, Pencil, X } from "lucide-react";
|
|
9
|
+
import { cn } from "../lib/utils.js";
|
|
10
|
+
import { Button } from "./button.js";
|
|
11
|
+
import { FilterQueryBar } from "./filter-query-bar.js";
|
|
12
|
+
import { Input } from "./input.js";
|
|
13
|
+
import { Label } from "./label.js";
|
|
14
|
+
import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
15
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
|
|
16
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
17
|
+
const ENTER_KEY = "Enter";
|
|
18
|
+
/** Suggestions of the query editor render in their own popover, outside the edit popover. */
|
|
19
|
+
const NESTED_POPOVER_SELECTOR = "[data-slot=\"popover-content\"]";
|
|
20
|
+
/**
|
|
21
|
+
* Tells whether a value is a non-null object.
|
|
22
|
+
* @param value - Untrusted value.
|
|
23
|
+
* @returns Whether its properties can be read.
|
|
24
|
+
*/
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return typeof value === "object" && value !== null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validates presets restored from untrusted storage, trimming names and queries and dropping
|
|
30
|
+
* malformed or empty entries.
|
|
31
|
+
* @param value - Parsed stored value, such as the result of `JSON.parse`.
|
|
32
|
+
* @returns The valid presets, or an empty list when the value is not a list.
|
|
33
|
+
*/
|
|
34
|
+
export function parseFilterPresets(value) {
|
|
35
|
+
if (!Array.isArray(value)) return [];
|
|
36
|
+
return value.flatMap((entry) => {
|
|
37
|
+
if (!isRecord(entry) || typeof entry.name !== "string" || typeof entry.query !== "string") return [];
|
|
38
|
+
const name = entry.name.trim();
|
|
39
|
+
const query = entry.query.trim();
|
|
40
|
+
return name && query ? [{
|
|
41
|
+
name,
|
|
42
|
+
query
|
|
43
|
+
}] : [];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export const FILTER_PRESET_DEFAULT_LABELS = {
|
|
47
|
+
saveAction: "Guardar filtro",
|
|
48
|
+
saveConfirm: "Guardar",
|
|
49
|
+
saveConfirmAriaLabel: "Guardar filtro con nombre",
|
|
50
|
+
presetName: "Nombre del filtro",
|
|
51
|
+
presetNamePlaceholder: "Mi filtro",
|
|
52
|
+
presetQuery: "Búsqueda del filtro",
|
|
53
|
+
presetQueryPlaceholder: "",
|
|
54
|
+
savedPresets: "Filtros guardados:",
|
|
55
|
+
editConfirmAriaLabel: "Guardar cambios del filtro",
|
|
56
|
+
cancel: "Cancelar",
|
|
57
|
+
delete: "Eliminar",
|
|
58
|
+
emptyNameError: "Ingresá un nombre para el filtro.",
|
|
59
|
+
emptyCurrentQueryError: "Escribí una búsqueda en la barra antes de guardarla.",
|
|
60
|
+
emptyPresetQueryError: "Ingresá una búsqueda para el filtro.",
|
|
61
|
+
duplicateNameError: "Ya existe un filtro con ese nombre.",
|
|
62
|
+
applyPresetAriaLabel: (presetName) => `Aplicar filtro guardado ${presetName}`,
|
|
63
|
+
editPresetAriaLabel: (presetName) => `Editar filtro guardado ${presetName}`,
|
|
64
|
+
deletePresetAriaLabel: (presetName) => `Eliminar filtro guardado ${presetName}`,
|
|
65
|
+
deleteConfirmation: (presetName) => `¿Querés eliminar el filtro guardado "${presetName}"?`
|
|
66
|
+
};
|
|
67
|
+
const FORM_POPOVER_CLASS_NAME = "grid w-64 gap-2";
|
|
68
|
+
const ERROR_CLASS_NAME = "m-0 text-xs text-destructive";
|
|
69
|
+
const CHIP_ICON_BUTTON_CLASS_NAME = "inline-flex cursor-pointer items-center border-0 bg-transparent py-[0.35rem] text-muted-foreground [&_svg]:size-3";
|
|
70
|
+
/**
|
|
71
|
+
* Compact icon button that saves the current query as a named preset. Fits the action slot of
|
|
72
|
+
* the filter bar input.
|
|
73
|
+
* @param props - Save availability, save callback and optional labels.
|
|
74
|
+
* @returns The button and its naming popover.
|
|
75
|
+
*/
|
|
76
|
+
export function FilterPresetSaveButton(t0) {
|
|
77
|
+
const $ = _c(45);
|
|
78
|
+
const { canSaveCurrentQuery, onSaveCurrentQuery, labels } = t0;
|
|
79
|
+
let t1;
|
|
80
|
+
if ($[0] !== labels) {
|
|
81
|
+
t1 = {
|
|
82
|
+
...FILTER_PRESET_DEFAULT_LABELS,
|
|
83
|
+
...labels
|
|
84
|
+
};
|
|
85
|
+
$[0] = labels;
|
|
86
|
+
$[1] = t1;
|
|
87
|
+
} else {
|
|
88
|
+
t1 = $[1];
|
|
89
|
+
}
|
|
90
|
+
const resolvedLabels = t1;
|
|
91
|
+
const nameInputId = useId();
|
|
92
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
93
|
+
const [nameDraft, setNameDraft] = useState("");
|
|
94
|
+
const [error, setError] = useState(null);
|
|
95
|
+
let t2;
|
|
96
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
97
|
+
t2 = (nextOpen) => {
|
|
98
|
+
setIsOpen(nextOpen);
|
|
99
|
+
if (!nextOpen) {
|
|
100
|
+
setNameDraft("");
|
|
101
|
+
setError(null);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
$[2] = t2;
|
|
105
|
+
} else {
|
|
106
|
+
t2 = $[2];
|
|
107
|
+
}
|
|
108
|
+
const handleOpenChange = t2;
|
|
109
|
+
let t3;
|
|
110
|
+
if ($[3] !== nameDraft || $[4] !== onSaveCurrentQuery || $[5] !== resolvedLabels.emptyCurrentQueryError || $[6] !== resolvedLabels.emptyNameError) {
|
|
111
|
+
t3 = () => {
|
|
112
|
+
const presetName = nameDraft.trim();
|
|
113
|
+
if (!presetName) {
|
|
114
|
+
setError(resolvedLabels.emptyNameError);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!onSaveCurrentQuery(presetName)) {
|
|
118
|
+
setError(resolvedLabels.emptyCurrentQueryError);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
handleOpenChange(false);
|
|
122
|
+
};
|
|
123
|
+
$[3] = nameDraft;
|
|
124
|
+
$[4] = onSaveCurrentQuery;
|
|
125
|
+
$[5] = resolvedLabels.emptyCurrentQueryError;
|
|
126
|
+
$[6] = resolvedLabels.emptyNameError;
|
|
127
|
+
$[7] = t3;
|
|
128
|
+
} else {
|
|
129
|
+
t3 = $[7];
|
|
130
|
+
}
|
|
131
|
+
const handleConfirmSave = t3;
|
|
132
|
+
const t4 = !canSaveCurrentQuery;
|
|
133
|
+
let t5;
|
|
134
|
+
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
|
135
|
+
t5 = /* @__PURE__ */ _jsx(Bookmark, { "aria-hidden": "true" });
|
|
136
|
+
$[8] = t5;
|
|
137
|
+
} else {
|
|
138
|
+
t5 = $[8];
|
|
139
|
+
}
|
|
140
|
+
let t6;
|
|
141
|
+
if ($[9] !== resolvedLabels.saveAction || $[10] !== t4) {
|
|
142
|
+
t6 = /* @__PURE__ */ _jsx(TooltipTrigger, {
|
|
143
|
+
asChild: true,
|
|
144
|
+
children: /* @__PURE__ */ _jsx(PopoverTrigger, {
|
|
145
|
+
asChild: true,
|
|
146
|
+
children: /* @__PURE__ */ _jsx(Button, {
|
|
147
|
+
"data-slot": "filter-preset-save-button",
|
|
148
|
+
"aria-label": resolvedLabels.saveAction,
|
|
149
|
+
disabled: t4,
|
|
150
|
+
size: "icon-xs",
|
|
151
|
+
type: "button",
|
|
152
|
+
variant: "ghost",
|
|
153
|
+
children: t5
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
$[9] = resolvedLabels.saveAction;
|
|
158
|
+
$[10] = t4;
|
|
159
|
+
$[11] = t6;
|
|
160
|
+
} else {
|
|
161
|
+
t6 = $[11];
|
|
162
|
+
}
|
|
163
|
+
let t7;
|
|
164
|
+
if ($[12] !== resolvedLabels.saveAction) {
|
|
165
|
+
t7 = /* @__PURE__ */ _jsx(TooltipContent, { children: resolvedLabels.saveAction });
|
|
166
|
+
$[12] = resolvedLabels.saveAction;
|
|
167
|
+
$[13] = t7;
|
|
168
|
+
} else {
|
|
169
|
+
t7 = $[13];
|
|
170
|
+
}
|
|
171
|
+
let t8;
|
|
172
|
+
if ($[14] !== t6 || $[15] !== t7) {
|
|
173
|
+
t8 = /* @__PURE__ */ _jsxs(Tooltip, { children: [t6, t7] });
|
|
174
|
+
$[14] = t6;
|
|
175
|
+
$[15] = t7;
|
|
176
|
+
$[16] = t8;
|
|
177
|
+
} else {
|
|
178
|
+
t8 = $[16];
|
|
179
|
+
}
|
|
180
|
+
let t9;
|
|
181
|
+
if ($[17] !== nameInputId || $[18] !== resolvedLabels.presetName) {
|
|
182
|
+
t9 = /* @__PURE__ */ _jsx(Label, {
|
|
183
|
+
htmlFor: nameInputId,
|
|
184
|
+
children: resolvedLabels.presetName
|
|
185
|
+
});
|
|
186
|
+
$[17] = nameInputId;
|
|
187
|
+
$[18] = resolvedLabels.presetName;
|
|
188
|
+
$[19] = t9;
|
|
189
|
+
} else {
|
|
190
|
+
t9 = $[19];
|
|
191
|
+
}
|
|
192
|
+
let t10;
|
|
193
|
+
if ($[20] !== error) {
|
|
194
|
+
t10 = (event) => {
|
|
195
|
+
setNameDraft(event.target.value);
|
|
196
|
+
if (error) {
|
|
197
|
+
setError(null);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
$[20] = error;
|
|
201
|
+
$[21] = t10;
|
|
202
|
+
} else {
|
|
203
|
+
t10 = $[21];
|
|
204
|
+
}
|
|
205
|
+
let t11;
|
|
206
|
+
if ($[22] !== handleConfirmSave) {
|
|
207
|
+
t11 = (event_0) => {
|
|
208
|
+
if (event_0.key !== ENTER_KEY) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
event_0.preventDefault();
|
|
212
|
+
handleConfirmSave();
|
|
213
|
+
};
|
|
214
|
+
$[22] = handleConfirmSave;
|
|
215
|
+
$[23] = t11;
|
|
216
|
+
} else {
|
|
217
|
+
t11 = $[23];
|
|
218
|
+
}
|
|
219
|
+
let t12;
|
|
220
|
+
if ($[24] !== nameDraft || $[25] !== nameInputId || $[26] !== resolvedLabels.presetNamePlaceholder || $[27] !== t10 || $[28] !== t11) {
|
|
221
|
+
t12 = /* @__PURE__ */ _jsx(Input, {
|
|
222
|
+
id: nameInputId,
|
|
223
|
+
onChange: t10,
|
|
224
|
+
onKeyDown: t11,
|
|
225
|
+
placeholder: resolvedLabels.presetNamePlaceholder,
|
|
226
|
+
type: "text",
|
|
227
|
+
value: nameDraft
|
|
228
|
+
});
|
|
229
|
+
$[24] = nameDraft;
|
|
230
|
+
$[25] = nameInputId;
|
|
231
|
+
$[26] = resolvedLabels.presetNamePlaceholder;
|
|
232
|
+
$[27] = t10;
|
|
233
|
+
$[28] = t11;
|
|
234
|
+
$[29] = t12;
|
|
235
|
+
} else {
|
|
236
|
+
t12 = $[29];
|
|
237
|
+
}
|
|
238
|
+
let t13;
|
|
239
|
+
if ($[30] !== error) {
|
|
240
|
+
t13 = error ? /* @__PURE__ */ _jsx("p", {
|
|
241
|
+
className: ERROR_CLASS_NAME,
|
|
242
|
+
role: "alert",
|
|
243
|
+
children: error
|
|
244
|
+
}) : null;
|
|
245
|
+
$[30] = error;
|
|
246
|
+
$[31] = t13;
|
|
247
|
+
} else {
|
|
248
|
+
t13 = $[31];
|
|
249
|
+
}
|
|
250
|
+
let t14;
|
|
251
|
+
if ($[32] !== handleConfirmSave || $[33] !== resolvedLabels.saveConfirm || $[34] !== resolvedLabels.saveConfirmAriaLabel) {
|
|
252
|
+
t14 = /* @__PURE__ */ _jsx(Button, {
|
|
253
|
+
"aria-label": resolvedLabels.saveConfirmAriaLabel,
|
|
254
|
+
onClick: handleConfirmSave,
|
|
255
|
+
size: "sm",
|
|
256
|
+
type: "button",
|
|
257
|
+
children: resolvedLabels.saveConfirm
|
|
258
|
+
});
|
|
259
|
+
$[32] = handleConfirmSave;
|
|
260
|
+
$[33] = resolvedLabels.saveConfirm;
|
|
261
|
+
$[34] = resolvedLabels.saveConfirmAriaLabel;
|
|
262
|
+
$[35] = t14;
|
|
263
|
+
} else {
|
|
264
|
+
t14 = $[35];
|
|
265
|
+
}
|
|
266
|
+
let t15;
|
|
267
|
+
if ($[36] !== t12 || $[37] !== t13 || $[38] !== t14 || $[39] !== t9) {
|
|
268
|
+
t15 = /* @__PURE__ */ _jsxs(PopoverContent, {
|
|
269
|
+
align: "end",
|
|
270
|
+
className: FORM_POPOVER_CLASS_NAME,
|
|
271
|
+
children: [
|
|
272
|
+
t9,
|
|
273
|
+
t12,
|
|
274
|
+
t13,
|
|
275
|
+
t14
|
|
276
|
+
]
|
|
277
|
+
});
|
|
278
|
+
$[36] = t12;
|
|
279
|
+
$[37] = t13;
|
|
280
|
+
$[38] = t14;
|
|
281
|
+
$[39] = t9;
|
|
282
|
+
$[40] = t15;
|
|
283
|
+
} else {
|
|
284
|
+
t15 = $[40];
|
|
285
|
+
}
|
|
286
|
+
let t16;
|
|
287
|
+
if ($[41] !== isOpen || $[42] !== t15 || $[43] !== t8) {
|
|
288
|
+
t16 = /* @__PURE__ */ _jsxs(Popover, {
|
|
289
|
+
onOpenChange: handleOpenChange,
|
|
290
|
+
open: isOpen,
|
|
291
|
+
children: [t8, t15]
|
|
292
|
+
});
|
|
293
|
+
$[41] = isOpen;
|
|
294
|
+
$[42] = t15;
|
|
295
|
+
$[43] = t8;
|
|
296
|
+
$[44] = t16;
|
|
297
|
+
} else {
|
|
298
|
+
t16 = $[44];
|
|
299
|
+
}
|
|
300
|
+
return t16;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Renders one chip per saved preset: its name applies it, the pencil edits its name and query,
|
|
304
|
+
* and the cross deletes it after a confirmation. Renders nothing without presets.
|
|
305
|
+
* @param props - Presets, filter configs, callbacks and optional labels.
|
|
306
|
+
* @returns The presets row, or nothing.
|
|
307
|
+
*/
|
|
308
|
+
export function FilterPresetsBar(t0) {
|
|
309
|
+
const $ = _c(4);
|
|
310
|
+
const { presets, queryFilterConfigs, onApplyPreset, onDeletePreset, onUpdatePreset, labels, className } = t0;
|
|
311
|
+
const resolvedLabels = {
|
|
312
|
+
...FILTER_PRESET_DEFAULT_LABELS,
|
|
313
|
+
...labels
|
|
314
|
+
};
|
|
315
|
+
const nameInputId = useId();
|
|
316
|
+
const [editingPresetName, setEditingPresetName] = useState(null);
|
|
317
|
+
const [nameDraft, setNameDraft] = useState("");
|
|
318
|
+
const [queryDraft, setQueryDraft] = useState("");
|
|
319
|
+
const [editError, setEditError] = useState(null);
|
|
320
|
+
const [deletingPresetName, setDeletingPresetName] = useState(null);
|
|
321
|
+
let t1;
|
|
322
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
323
|
+
t1 = (preset, nextOpen) => {
|
|
324
|
+
setEditError(null);
|
|
325
|
+
if (!nextOpen) {
|
|
326
|
+
setEditingPresetName(null);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
setEditingPresetName(preset.name);
|
|
330
|
+
setNameDraft(preset.name);
|
|
331
|
+
setQueryDraft(preset.query);
|
|
332
|
+
};
|
|
333
|
+
$[0] = t1;
|
|
334
|
+
} else {
|
|
335
|
+
t1 = $[0];
|
|
336
|
+
}
|
|
337
|
+
const handleEditOpenChange = t1;
|
|
338
|
+
const handleConfirmEdit = () => {
|
|
339
|
+
if (editingPresetName === null) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const name = nameDraft.trim();
|
|
343
|
+
const query = queryDraft.trim();
|
|
344
|
+
if (!name) {
|
|
345
|
+
setEditError(resolvedLabels.emptyNameError);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (!query) {
|
|
349
|
+
setEditError(resolvedLabels.emptyPresetQueryError);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (presets.some((preset_0) => preset_0.name === name && preset_0.name !== editingPresetName)) {
|
|
353
|
+
setEditError(resolvedLabels.duplicateNameError);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
onUpdatePreset({
|
|
357
|
+
name,
|
|
358
|
+
originalName: editingPresetName,
|
|
359
|
+
query
|
|
360
|
+
});
|
|
361
|
+
setEditingPresetName(null);
|
|
362
|
+
};
|
|
363
|
+
if (presets.length === 0) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
let t2;
|
|
367
|
+
if ($[1] !== className) {
|
|
368
|
+
t2 = cn("flex flex-wrap items-center gap-[0.4rem]", className);
|
|
369
|
+
$[1] = className;
|
|
370
|
+
$[2] = t2;
|
|
371
|
+
} else {
|
|
372
|
+
t2 = $[2];
|
|
373
|
+
}
|
|
374
|
+
let t3;
|
|
375
|
+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
376
|
+
t3 = /* @__PURE__ */ _jsx(Bookmark, { "aria-hidden": "true" });
|
|
377
|
+
$[3] = t3;
|
|
378
|
+
} else {
|
|
379
|
+
t3 = $[3];
|
|
380
|
+
}
|
|
381
|
+
return /* @__PURE__ */ _jsxs("div", {
|
|
382
|
+
"data-slot": "filter-presets-bar",
|
|
383
|
+
className: t2,
|
|
384
|
+
children: [/* @__PURE__ */ _jsxs("span", {
|
|
385
|
+
className: "inline-flex items-center gap-[0.3rem] text-xs font-medium text-muted-foreground [&_svg]:size-[0.8rem]",
|
|
386
|
+
children: [t3, resolvedLabels.savedPresets]
|
|
387
|
+
}), presets.map((preset_1) => /* @__PURE__ */ _jsxs("span", {
|
|
388
|
+
"data-slot": "filter-preset-chip",
|
|
389
|
+
className: "inline-flex items-center overflow-hidden rounded-full border border-border bg-muted text-xs leading-none",
|
|
390
|
+
children: [
|
|
391
|
+
/* @__PURE__ */ _jsx("button", {
|
|
392
|
+
"aria-label": resolvedLabels.applyPresetAriaLabel(preset_1.name),
|
|
393
|
+
className: "max-w-48 cursor-pointer truncate border-0 bg-transparent py-[0.35rem] pr-1 pl-[0.65rem] text-inherit hover:text-primary focus-visible:text-primary",
|
|
394
|
+
onClick: () => onApplyPreset(preset_1),
|
|
395
|
+
title: preset_1.query,
|
|
396
|
+
type: "button",
|
|
397
|
+
children: preset_1.name
|
|
398
|
+
}),
|
|
399
|
+
/* @__PURE__ */ _jsxs(Popover, {
|
|
400
|
+
onOpenChange: (nextOpen_0) => handleEditOpenChange(preset_1, nextOpen_0),
|
|
401
|
+
open: editingPresetName === preset_1.name,
|
|
402
|
+
children: [/* @__PURE__ */ _jsx(PopoverTrigger, {
|
|
403
|
+
asChild: true,
|
|
404
|
+
children: /* @__PURE__ */ _jsx("button", {
|
|
405
|
+
"aria-label": resolvedLabels.editPresetAriaLabel(preset_1.name),
|
|
406
|
+
className: cn(CHIP_ICON_BUTTON_CLASS_NAME, "px-[0.15rem] hover:text-primary focus-visible:text-primary"),
|
|
407
|
+
type: "button",
|
|
408
|
+
children: /* @__PURE__ */ _jsx(Pencil, { "aria-hidden": "true" })
|
|
409
|
+
})
|
|
410
|
+
}), /* @__PURE__ */ _jsxs(PopoverContent, {
|
|
411
|
+
align: "start",
|
|
412
|
+
className: FORM_POPOVER_CLASS_NAME,
|
|
413
|
+
onInteractOutside: _temp,
|
|
414
|
+
children: [
|
|
415
|
+
/* @__PURE__ */ _jsx(Label, {
|
|
416
|
+
htmlFor: nameInputId,
|
|
417
|
+
children: resolvedLabels.presetName
|
|
418
|
+
}),
|
|
419
|
+
/* @__PURE__ */ _jsx(Input, {
|
|
420
|
+
id: nameInputId,
|
|
421
|
+
onChange: (event_0) => {
|
|
422
|
+
setNameDraft(event_0.target.value);
|
|
423
|
+
if (editError) {
|
|
424
|
+
setEditError(null);
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
type: "text",
|
|
428
|
+
value: nameDraft
|
|
429
|
+
}),
|
|
430
|
+
/* @__PURE__ */ _jsx("span", {
|
|
431
|
+
className: "text-sm leading-none font-medium",
|
|
432
|
+
children: resolvedLabels.presetQuery
|
|
433
|
+
}),
|
|
434
|
+
/* @__PURE__ */ _jsx(FilterQueryBar, {
|
|
435
|
+
ariaLabel: resolvedLabels.presetQuery,
|
|
436
|
+
configs: queryFilterConfigs,
|
|
437
|
+
onValueChange: (nextQuery) => {
|
|
438
|
+
setQueryDraft(nextQuery);
|
|
439
|
+
if (editError) {
|
|
440
|
+
setEditError(null);
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
placeholder: resolvedLabels.presetQueryPlaceholder,
|
|
444
|
+
value: queryDraft
|
|
445
|
+
}),
|
|
446
|
+
editError ? /* @__PURE__ */ _jsx("p", {
|
|
447
|
+
className: ERROR_CLASS_NAME,
|
|
448
|
+
role: "alert",
|
|
449
|
+
children: editError
|
|
450
|
+
}) : null,
|
|
451
|
+
/* @__PURE__ */ _jsx(Button, {
|
|
452
|
+
"aria-label": resolvedLabels.editConfirmAriaLabel,
|
|
453
|
+
onClick: handleConfirmEdit,
|
|
454
|
+
size: "sm",
|
|
455
|
+
type: "button",
|
|
456
|
+
children: resolvedLabels.saveConfirm
|
|
457
|
+
})
|
|
458
|
+
]
|
|
459
|
+
})]
|
|
460
|
+
}),
|
|
461
|
+
/* @__PURE__ */ _jsxs(Popover, {
|
|
462
|
+
onOpenChange: (nextOpen_1) => setDeletingPresetName(nextOpen_1 ? preset_1.name : null),
|
|
463
|
+
open: deletingPresetName === preset_1.name,
|
|
464
|
+
children: [/* @__PURE__ */ _jsx(PopoverTrigger, {
|
|
465
|
+
asChild: true,
|
|
466
|
+
children: /* @__PURE__ */ _jsx("button", {
|
|
467
|
+
"aria-label": resolvedLabels.deletePresetAriaLabel(preset_1.name),
|
|
468
|
+
className: cn(CHIP_ICON_BUTTON_CLASS_NAME, "pr-2 pl-[0.15rem] hover:text-destructive focus-visible:text-destructive"),
|
|
469
|
+
type: "button",
|
|
470
|
+
children: /* @__PURE__ */ _jsx(X, { "aria-hidden": "true" })
|
|
471
|
+
})
|
|
472
|
+
}), /* @__PURE__ */ _jsxs(PopoverContent, {
|
|
473
|
+
align: "start",
|
|
474
|
+
className: "grid w-68 gap-3",
|
|
475
|
+
children: [/* @__PURE__ */ _jsx("p", {
|
|
476
|
+
className: "m-0 text-sm",
|
|
477
|
+
children: resolvedLabels.deleteConfirmation(preset_1.name)
|
|
478
|
+
}), /* @__PURE__ */ _jsxs("div", {
|
|
479
|
+
className: "flex justify-end gap-2",
|
|
480
|
+
children: [/* @__PURE__ */ _jsx(Button, {
|
|
481
|
+
onClick: () => setDeletingPresetName(null),
|
|
482
|
+
size: "sm",
|
|
483
|
+
type: "button",
|
|
484
|
+
variant: "outline",
|
|
485
|
+
children: resolvedLabels.cancel
|
|
486
|
+
}), /* @__PURE__ */ _jsx(Button, {
|
|
487
|
+
onClick: () => {
|
|
488
|
+
setDeletingPresetName(null);
|
|
489
|
+
onDeletePreset(preset_1.name);
|
|
490
|
+
},
|
|
491
|
+
size: "sm",
|
|
492
|
+
type: "button",
|
|
493
|
+
variant: "destructive",
|
|
494
|
+
children: resolvedLabels.delete
|
|
495
|
+
})]
|
|
496
|
+
})]
|
|
497
|
+
})]
|
|
498
|
+
})
|
|
499
|
+
]
|
|
500
|
+
}, preset_1.name))]
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
function _temp(event) {
|
|
504
|
+
const interactionTarget = event.target;
|
|
505
|
+
if (interactionTarget instanceof Element && interactionTarget.closest(NESTED_POPOVER_SELECTOR)) {
|
|
506
|
+
event.preventDefault();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
@@ -9,7 +9,6 @@ const PRESENCE_SWAP_ELEMENTS = {
|
|
|
9
9
|
div: motion.div,
|
|
10
10
|
span: motion.span
|
|
11
11
|
};
|
|
12
|
-
const INSTANT_TRANSITION = { duration: 0 };
|
|
13
12
|
/**
|
|
14
13
|
* One keyed state of the swap. While it animates out it turns inert and hidden
|
|
15
14
|
* from assistive technology, so stale controls cannot be clicked or announced.
|
|
@@ -17,7 +16,7 @@ const INSTANT_TRANSITION = { duration: 0 };
|
|
|
17
16
|
* @returns The animated state.
|
|
18
17
|
*/
|
|
19
18
|
function PresenceSwapItem(t0) {
|
|
20
|
-
const $ = _c(
|
|
19
|
+
const $ = _c(14);
|
|
21
20
|
const { as, className, children } = t0;
|
|
22
21
|
const MotionElement = PRESENCE_SWAP_ELEMENTS[as];
|
|
23
22
|
const isPresent = useIsPresent();
|
|
@@ -37,78 +36,66 @@ function PresenceSwapItem(t0) {
|
|
|
37
36
|
t3 = $[1];
|
|
38
37
|
}
|
|
39
38
|
let t4;
|
|
40
|
-
if ($[2]
|
|
41
|
-
t4 =
|
|
42
|
-
duration: MOTION_TIMING.enter,
|
|
43
|
-
ease: MOTION_EASE
|
|
44
|
-
};
|
|
45
|
-
$[2] = shouldReduceMotion;
|
|
46
|
-
$[3] = t4;
|
|
47
|
-
} else {
|
|
48
|
-
t4 = $[3];
|
|
49
|
-
}
|
|
50
|
-
let t5;
|
|
51
|
-
if ($[4] !== t4) {
|
|
52
|
-
t5 = {
|
|
39
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
40
|
+
t4 = {
|
|
53
41
|
opacity: 1,
|
|
54
42
|
y: 0,
|
|
55
|
-
transition:
|
|
43
|
+
transition: {
|
|
44
|
+
duration: MOTION_TIMING.enter,
|
|
45
|
+
ease: MOTION_EASE
|
|
46
|
+
}
|
|
56
47
|
};
|
|
57
|
-
$[
|
|
58
|
-
$[5] = t5;
|
|
48
|
+
$[2] = t4;
|
|
59
49
|
} else {
|
|
60
|
-
|
|
50
|
+
t4 = $[2];
|
|
61
51
|
}
|
|
62
|
-
const
|
|
63
|
-
let
|
|
64
|
-
if ($[
|
|
65
|
-
|
|
52
|
+
const t5 = -distance;
|
|
53
|
+
let t6;
|
|
54
|
+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
55
|
+
t6 = {
|
|
66
56
|
duration: MOTION_TIMING.exit,
|
|
67
57
|
ease: MOTION_EASE
|
|
68
58
|
};
|
|
69
|
-
$[
|
|
70
|
-
$[7] = t7;
|
|
59
|
+
$[3] = t6;
|
|
71
60
|
} else {
|
|
72
|
-
|
|
61
|
+
t6 = $[3];
|
|
73
62
|
}
|
|
74
|
-
let
|
|
75
|
-
if ($[
|
|
76
|
-
|
|
63
|
+
let t7;
|
|
64
|
+
if ($[4] !== t5) {
|
|
65
|
+
t7 = {
|
|
77
66
|
opacity: 0,
|
|
78
|
-
y:
|
|
79
|
-
transition:
|
|
67
|
+
y: t5,
|
|
68
|
+
transition: t6
|
|
80
69
|
};
|
|
81
|
-
$[
|
|
82
|
-
$[
|
|
83
|
-
$[10] = t8;
|
|
70
|
+
$[4] = t5;
|
|
71
|
+
$[5] = t7;
|
|
84
72
|
} else {
|
|
85
|
-
|
|
73
|
+
t7 = $[5];
|
|
86
74
|
}
|
|
87
|
-
let
|
|
88
|
-
if ($[
|
|
89
|
-
|
|
75
|
+
let t8;
|
|
76
|
+
if ($[6] !== MotionElement || $[7] !== children || $[8] !== className || $[9] !== t1 || $[10] !== t2 || $[11] !== t3 || $[12] !== t7) {
|
|
77
|
+
t8 = /* @__PURE__ */ _jsx(MotionElement, {
|
|
90
78
|
"data-slot": "presence-swap",
|
|
91
79
|
"aria-hidden": t1,
|
|
92
80
|
inert: t2,
|
|
93
81
|
className,
|
|
94
82
|
initial: t3,
|
|
95
|
-
animate:
|
|
96
|
-
exit:
|
|
83
|
+
animate: t4,
|
|
84
|
+
exit: t7,
|
|
97
85
|
children
|
|
98
86
|
});
|
|
99
|
-
$[
|
|
100
|
-
$[
|
|
101
|
-
$[
|
|
102
|
-
$[
|
|
103
|
-
$[
|
|
104
|
-
$[
|
|
105
|
-
$[
|
|
106
|
-
$[
|
|
107
|
-
$[19] = t9;
|
|
87
|
+
$[6] = MotionElement;
|
|
88
|
+
$[7] = children;
|
|
89
|
+
$[8] = className;
|
|
90
|
+
$[9] = t1;
|
|
91
|
+
$[10] = t2;
|
|
92
|
+
$[11] = t3;
|
|
93
|
+
$[12] = t7;
|
|
94
|
+
$[13] = t8;
|
|
108
95
|
} else {
|
|
109
|
-
|
|
96
|
+
t8 = $[13];
|
|
110
97
|
}
|
|
111
|
-
return
|
|
98
|
+
return t8;
|
|
112
99
|
}
|
|
113
100
|
/**
|
|
114
101
|
* Swaps keyed content with a short lift-and-fade; the first render is not animated.
|
|
@@ -10,8 +10,13 @@ export interface ReactionButtonProps {
|
|
|
10
10
|
count: number;
|
|
11
11
|
onClick: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
12
12
|
isDisabled?: boolean;
|
|
13
|
-
/** Icon of the reaction
|
|
13
|
+
/** Icon of the reaction; it is filled with `activeColor` while active. */
|
|
14
14
|
icon?: ComponentType<SVGProps<SVGSVGElement>>;
|
|
15
|
+
/**
|
|
16
|
+
* CSS color of the active icon, such as `var(--primary)` or `currentColor` to follow the
|
|
17
|
+
* button text. Defaults to the destructive color, the usual tone of a like.
|
|
18
|
+
*/
|
|
19
|
+
activeColor?: string;
|
|
15
20
|
/** Formats the visible count, for example with a locale-aware compact format. */
|
|
16
21
|
formatCount?: (count: number) => string;
|
|
17
22
|
className?: string;
|
|
@@ -23,4 +28,4 @@ export interface ReactionButtonProps {
|
|
|
23
28
|
* @param props - Accessible name, state, count, click handler and optional icon.
|
|
24
29
|
* @returns The reaction button.
|
|
25
30
|
*/
|
|
26
|
-
export declare function ReactionButton({ ariaLabel, isActive, count, onClick, isDisabled, icon: Icon, formatCount, className, }: ReactionButtonProps): import("react").JSX.Element;
|
|
31
|
+
export declare function ReactionButton({ ariaLabel, isActive, count, onClick, isDisabled, icon: Icon, formatCount, activeColor, className, }: ReactionButtonProps): import("react").JSX.Element;
|