@mediaradar/design-components 0.7.0 → 0.8.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/dist/index.js CHANGED
@@ -2911,7 +2911,613 @@ function WorkspaceAvatar({ name, size = "md" }) {
2911
2911
  }
2912
2912
  );
2913
2913
  }
2914
+
2915
+ // src/Tag.tsx
2916
+ import { jsx as jsx32 } from "react/jsx-runtime";
2917
+ function Tag({ children, className }) {
2918
+ return /* @__PURE__ */ jsx32(
2919
+ "span",
2920
+ {
2921
+ className: cn(
2922
+ "inline-flex items-center whitespace-nowrap rounded-full bg-subtle px-2 py-0.5 text-[11px] font-medium text-text-secondary",
2923
+ className
2924
+ ),
2925
+ children
2926
+ }
2927
+ );
2928
+ }
2929
+
2930
+ // src/TablePagination.tsx
2931
+ import { ChevronDown as ChevronDown9, ChevronFirst, ChevronLast, ChevronLeft as ChevronLeft4, ChevronRight as ChevronRight5 } from "lucide-react";
2932
+ import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
2933
+ function TablePagination({
2934
+ page,
2935
+ perPage,
2936
+ totalItems,
2937
+ onPageChange,
2938
+ onPerPageChange,
2939
+ perPageOptions = [25, 50, 100],
2940
+ itemLabel = "results",
2941
+ className
2942
+ }) {
2943
+ const totalPages = Math.max(1, Math.ceil(totalItems / perPage));
2944
+ const current = Math.min(page, totalPages);
2945
+ const rangeStart = totalItems === 0 ? 0 : (current - 1) * perPage + 1;
2946
+ const rangeEnd = Math.min(current * perPage, totalItems);
2947
+ const btn = "flex h-8 min-w-8 items-center justify-center rounded-control px-2 text-[13px] transition-colors";
2948
+ const stepBtn = cn(
2949
+ btn,
2950
+ "text-text-secondary hover:bg-subtle hover:text-text-primary disabled:pointer-events-none disabled:opacity-30"
2951
+ );
2952
+ return /* @__PURE__ */ jsxs29("div", { className: cn("flex flex-wrap items-center justify-between gap-x-4 gap-y-2", className), children: [
2953
+ /* @__PURE__ */ jsxs29("label", { className: "flex items-center gap-2 text-[13px] text-text-secondary", children: [
2954
+ /* @__PURE__ */ jsxs29("span", { className: "relative", children: [
2955
+ /* @__PURE__ */ jsx33(
2956
+ "select",
2957
+ {
2958
+ value: perPage,
2959
+ onChange: (e) => onPerPageChange(Number(e.target.value)),
2960
+ "aria-label": "Items per page",
2961
+ className: "appearance-none rounded-control border border-border-default bg-input py-1 pl-2.5 pr-7 text-[13px] font-medium text-text-primary focus:outline focus:outline-2 focus:outline-border-focus",
2962
+ children: perPageOptions.map((n) => /* @__PURE__ */ jsx33("option", { value: n, children: n }, n))
2963
+ }
2964
+ ),
2965
+ /* @__PURE__ */ jsx33(
2966
+ ChevronDown9,
2967
+ {
2968
+ size: 13,
2969
+ "aria-hidden": "true",
2970
+ className: "pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-text-secondary"
2971
+ }
2972
+ )
2973
+ ] }),
2974
+ "items per page"
2975
+ ] }),
2976
+ /* @__PURE__ */ jsxs29("nav", { className: "flex items-center gap-1", "aria-label": "Pagination", children: [
2977
+ /* @__PURE__ */ jsx33(
2978
+ "button",
2979
+ {
2980
+ type: "button",
2981
+ onClick: () => onPageChange(1),
2982
+ disabled: current === 1,
2983
+ "aria-label": "First page",
2984
+ className: stepBtn,
2985
+ children: /* @__PURE__ */ jsx33(ChevronFirst, { size: 16, "aria-hidden": "true" })
2986
+ }
2987
+ ),
2988
+ /* @__PURE__ */ jsx33(
2989
+ "button",
2990
+ {
2991
+ type: "button",
2992
+ onClick: () => onPageChange(current - 1),
2993
+ disabled: current === 1,
2994
+ "aria-label": "Previous page",
2995
+ className: stepBtn,
2996
+ children: /* @__PURE__ */ jsx33(ChevronLeft4, { size: 16, "aria-hidden": "true" })
2997
+ }
2998
+ ),
2999
+ pageWindow(current, totalPages).map(
3000
+ (p) => typeof p === "string" ? /* @__PURE__ */ jsx33("span", { className: "px-1 text-[13px] text-text-tertiary", children: "\u2026" }, p) : /* @__PURE__ */ jsx33(
3001
+ "button",
3002
+ {
3003
+ type: "button",
3004
+ onClick: () => onPageChange(p),
3005
+ "aria-current": p === current ? "page" : void 0,
3006
+ className: cn(
3007
+ btn,
3008
+ p === current ? "bg-brand-primaryAction font-semibold text-brand-onprimary" : "text-text-secondary hover:bg-subtle hover:text-text-primary"
3009
+ ),
3010
+ children: p
3011
+ },
3012
+ p
3013
+ )
3014
+ ),
3015
+ /* @__PURE__ */ jsx33(
3016
+ "button",
3017
+ {
3018
+ type: "button",
3019
+ onClick: () => onPageChange(current + 1),
3020
+ disabled: current === totalPages,
3021
+ "aria-label": "Next page",
3022
+ className: stepBtn,
3023
+ children: /* @__PURE__ */ jsx33(ChevronRight5, { size: 16, "aria-hidden": "true" })
3024
+ }
3025
+ ),
3026
+ /* @__PURE__ */ jsx33(
3027
+ "button",
3028
+ {
3029
+ type: "button",
3030
+ onClick: () => onPageChange(totalPages),
3031
+ disabled: current === totalPages,
3032
+ "aria-label": "Last page",
3033
+ className: stepBtn,
3034
+ children: /* @__PURE__ */ jsx33(ChevronLast, { size: 16, "aria-hidden": "true" })
3035
+ }
3036
+ )
3037
+ ] }),
3038
+ /* @__PURE__ */ jsxs29("span", { className: "text-[13px] text-text-tertiary tabular-nums", children: [
3039
+ rangeStart.toLocaleString(),
3040
+ " \u2013 ",
3041
+ rangeEnd.toLocaleString(),
3042
+ " of ",
3043
+ totalItems.toLocaleString(),
3044
+ " ",
3045
+ itemLabel
3046
+ ] })
3047
+ ] });
3048
+ }
3049
+
3050
+ // src/DateRangePicker.tsx
3051
+ import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef11, useState as useState12 } from "react";
3052
+ import { ChevronDown as ChevronDown10 } from "lucide-react";
3053
+ import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
3054
+ var MONTH_ABBR = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3055
+ var PRESETS = ["Rolling 3 months", "Rolling 6 months", "Rolling 12 months"];
3056
+ var startOfToday = () => {
3057
+ const d = /* @__PURE__ */ new Date();
3058
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate());
3059
+ };
3060
+ var fmtDate = (d) => d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
3061
+ function resolveRange(label, today = startOfToday()) {
3062
+ const end = today;
3063
+ const mMonths = label.match(/Rolling (\d+) months/);
3064
+ if (mMonths) {
3065
+ return [new Date(end.getFullYear(), end.getMonth() - Number(mMonths[1]), 1), end];
3066
+ }
3067
+ const mQuarters = label.match(/Rolling (\d+) quarters/);
3068
+ if (mQuarters) {
3069
+ return [new Date(end.getFullYear(), end.getMonth() - Number(mQuarters[1]) * 3, 1), end];
3070
+ }
3071
+ const mYears = label.match(/Rolling (\d+) years/);
3072
+ if (mYears) {
3073
+ return [new Date(end.getFullYear() - Number(mYears[1]), end.getMonth(), 1), end];
3074
+ }
3075
+ const mCustom = label.match(/([A-Za-z]{3})\s+(\d{4}).*?([A-Za-z]{3})\s+(\d{4})/);
3076
+ if (mCustom) {
3077
+ const s = new Date(Number(mCustom[2]), MONTH_ABBR.indexOf(mCustom[1]), 1);
3078
+ const e = new Date(Number(mCustom[4]), MONTH_ABBR.indexOf(mCustom[3]) + 1, 0);
3079
+ return [s, e];
3080
+ }
3081
+ return [new Date(end.getFullYear(), end.getMonth() - 6, 1), end];
3082
+ }
3083
+ function spanLabel(label, today) {
3084
+ const [s, e] = resolveRange(label, today);
3085
+ return `${fmtDate(s)} \u2013 ${fmtDate(e)}`;
3086
+ }
3087
+ function MiniSelect({ value, onChange, options }) {
3088
+ return /* @__PURE__ */ jsx34(
3089
+ "select",
3090
+ {
3091
+ value: String(value),
3092
+ onChange: (e) => {
3093
+ const opt = options.find((o) => String(o.value) === e.target.value);
3094
+ if (opt) onChange(opt.value);
3095
+ },
3096
+ className: "rounded-control border border-border-default bg-input px-1.5 py-1 text-[12px] text-text-primary outline-hidden focus:border-border-focus",
3097
+ children: options.map((o) => /* @__PURE__ */ jsx34("option", { value: String(o.value), children: o.label }, String(o.value)))
3098
+ }
3099
+ );
3100
+ }
3101
+ function DateRangePicker({
3102
+ defaultValue = "Rolling 6 months",
3103
+ align = "left",
3104
+ presets = PRESETS,
3105
+ onChange,
3106
+ onRangeChange,
3107
+ showFooter = false,
3108
+ today,
3109
+ years
3110
+ }) {
3111
+ const end = useMemo4(() => today ?? startOfToday(), [today]);
3112
+ const yearOptions = years ?? [3, 2, 1, 0].map((n) => end.getFullYear() - n);
3113
+ const [open, setOpen] = useState12(false);
3114
+ const [value, setValue] = useState12(defaultValue);
3115
+ const [draft, setDraft] = useState12(defaultValue);
3116
+ const ref = useRef11(null);
3117
+ const [fromMo, setFromMo] = useState12(end.getMonth());
3118
+ const [fromYr, setFromYr] = useState12(end.getFullYear() - 1);
3119
+ const [toMo, setToMo] = useState12(end.getMonth());
3120
+ const [toYr, setToYr] = useState12(end.getFullYear());
3121
+ useEffect11(() => {
3122
+ const [s, e] = resolveRange(value, end);
3123
+ onRangeChange?.(s, e);
3124
+ }, [value]);
3125
+ const toggleOpen = () => {
3126
+ if (!open) setDraft(value);
3127
+ setOpen((o) => !o);
3128
+ };
3129
+ useEffect11(() => {
3130
+ if (!open) return;
3131
+ const onDown = (e) => {
3132
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
3133
+ };
3134
+ const onKey = (e) => e.key === "Escape" && setOpen(false);
3135
+ window.addEventListener("mousedown", onDown);
3136
+ window.addEventListener("keydown", onKey);
3137
+ return () => {
3138
+ window.removeEventListener("mousedown", onDown);
3139
+ window.removeEventListener("keydown", onKey);
3140
+ };
3141
+ }, [open]);
3142
+ const commit = (label) => {
3143
+ setValue(label);
3144
+ onChange?.(label);
3145
+ setOpen(false);
3146
+ };
3147
+ const span = toYr * 12 + toMo - (fromYr * 12 + fromMo) + 1;
3148
+ const valid = span >= 1;
3149
+ const applyCustom = () => {
3150
+ if (!valid) return;
3151
+ const label = `${MONTH_ABBR[fromMo]} ${fromYr} \u2013 ${MONTH_ABBR[toMo]} ${toYr}`;
3152
+ if (showFooter) setDraft(label);
3153
+ else commit(label);
3154
+ };
3155
+ return /* @__PURE__ */ jsxs30("div", { className: "relative", ref, children: [
3156
+ /* @__PURE__ */ jsxs30(
3157
+ "button",
3158
+ {
3159
+ type: "button",
3160
+ onClick: toggleOpen,
3161
+ "aria-expanded": open,
3162
+ "aria-haspopup": "listbox",
3163
+ className: chipTriggerClass(),
3164
+ children: [
3165
+ /* @__PURE__ */ jsxs30("span", { className: "flex flex-col gap-1 text-left leading-none", children: [
3166
+ /* @__PURE__ */ jsx34("span", { className: "text-[10px] text-text-tertiary", children: spanLabel(value, end) }),
3167
+ /* @__PURE__ */ jsx34("span", { className: "text-[12px] font-medium text-text-primary", children: value })
3168
+ ] }),
3169
+ /* @__PURE__ */ jsx34(ChevronDown10, { size: 14, "aria-hidden": "true", className: cn("shrink-0 text-text-secondary transition-transform", open && "rotate-180") })
3170
+ ]
3171
+ }
3172
+ ),
3173
+ open && /* @__PURE__ */ jsxs30("div", { className: cn("absolute top-[calc(100%+8px)] z-30 w-[280px] overflow-hidden rounded-card border border-border-default bg-surface py-1 shadow-overlay", align === "right" ? "right-0" : "left-0"), children: [
3174
+ presets.map((p) => /* @__PURE__ */ jsx34(
3175
+ "button",
3176
+ {
3177
+ type: "button",
3178
+ onClick: () => showFooter ? setDraft(p) : commit(p),
3179
+ className: cn("block w-full px-3 py-2 text-left text-[13px] transition-colors hover:bg-subtle", (showFooter ? draft : value) === p ? "font-semibold text-brand-primaryAction" : "text-text-secondary"),
3180
+ children: p
3181
+ },
3182
+ p
3183
+ )),
3184
+ /* @__PURE__ */ jsxs30("div", { className: "mt-1 border-t border-border-default px-3 pb-2 pt-2", children: [
3185
+ /* @__PURE__ */ jsx34("div", { className: "text-[13px] font-semibold text-text-primary", children: "Custom Range" }),
3186
+ /* @__PURE__ */ jsxs30("div", { className: "mt-2 flex flex-col gap-2", children: [
3187
+ /* @__PURE__ */ jsxs30("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3188
+ "From",
3189
+ /* @__PURE__ */ jsxs30("span", { className: "flex gap-1", children: [
3190
+ /* @__PURE__ */ jsx34(MiniSelect, { value: fromMo, onChange: setFromMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3191
+ /* @__PURE__ */ jsx34(MiniSelect, { value: fromYr, onChange: setFromYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3192
+ ] })
3193
+ ] }),
3194
+ /* @__PURE__ */ jsxs30("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3195
+ "To",
3196
+ /* @__PURE__ */ jsxs30("span", { className: "flex gap-1", children: [
3197
+ /* @__PURE__ */ jsx34(MiniSelect, { value: toMo, onChange: setToMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3198
+ /* @__PURE__ */ jsx34(MiniSelect, { value: toYr, onChange: setToYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3199
+ ] })
3200
+ ] }),
3201
+ /* @__PURE__ */ jsx34(
3202
+ "button",
3203
+ {
3204
+ type: "button",
3205
+ onClick: applyCustom,
3206
+ disabled: !valid,
3207
+ className: "self-start text-[13px] font-semibold text-brand-primaryAction transition-opacity hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-40",
3208
+ children: showFooter ? "Use custom range" : "Apply"
3209
+ }
3210
+ )
3211
+ ] })
3212
+ ] }),
3213
+ showFooter && /* @__PURE__ */ jsx34(FilterDropdownFooter, { onApply: () => commit(draft) })
3214
+ ] })
3215
+ ] });
3216
+ }
3217
+
3218
+ // src/MultiSelectFilter.tsx
3219
+ import { useCallback as useCallback4, useEffect as useEffect12, useRef as useRef12, useState as useState13 } from "react";
3220
+ import { ChevronDown as ChevronDown11, Check as Check7, Minus as Minus2, Search as Search5, X as X4 } from "lucide-react";
3221
+ import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
3222
+ function MultiSelectFilter({
3223
+ caption,
3224
+ options = [],
3225
+ groups,
3226
+ selected,
3227
+ onChange,
3228
+ allLabel = "All",
3229
+ searchable = false,
3230
+ searchPlaceholder,
3231
+ align = "left",
3232
+ fullIsAll = false,
3233
+ min = 0,
3234
+ icon,
3235
+ showFooter = false,
3236
+ clearValue = [],
3237
+ menuWidthClass = "w-60",
3238
+ plainParent = false,
3239
+ fullWidth = false
3240
+ }) {
3241
+ const groupLeaves = (g) => g.children.length ? g.children : [{ id: g.id, label: g.label }];
3242
+ const leafOptions = groups ? groups.flatMap(groupLeaves) : options;
3243
+ const [open, setOpen] = useState13(false);
3244
+ const [q, setQ] = useState13("");
3245
+ const [draft, setDraft] = useState13(selected);
3246
+ const ref = useRef12(null);
3247
+ const close = useCallback4(() => {
3248
+ setOpen(false);
3249
+ setQ("");
3250
+ if (showFooter) return;
3251
+ if (draft.length !== selected.length || draft.some((id) => !selected.includes(id))) {
3252
+ onChange(draft);
3253
+ }
3254
+ }, [draft, selected, onChange, showFooter]);
3255
+ const openTray = () => {
3256
+ setDraft(selected);
3257
+ setOpen(true);
3258
+ };
3259
+ const apply = () => {
3260
+ onChange(draft);
3261
+ setOpen(false);
3262
+ setQ("");
3263
+ };
3264
+ useEffect12(() => {
3265
+ if (!open) return;
3266
+ const onKey = (e) => e.key === "Escape" && close();
3267
+ const onClick = (e) => {
3268
+ if (ref.current && !ref.current.contains(e.target)) close();
3269
+ };
3270
+ window.addEventListener("keydown", onKey);
3271
+ window.addEventListener("mousedown", onClick);
3272
+ return () => {
3273
+ window.removeEventListener("keydown", onKey);
3274
+ window.removeEventListener("mousedown", onClick);
3275
+ };
3276
+ }, [open, close]);
3277
+ const toggle = (id) => setDraft((cur) => {
3278
+ const next = cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id];
3279
+ if (next.length < min) return cur;
3280
+ return next;
3281
+ });
3282
+ const toggleGroup = (g) => setDraft((cur) => {
3283
+ const ids = groupLeaves(g).map((c) => c.id);
3284
+ const allSel = ids.every((id) => cur.includes(id));
3285
+ const next = allSel ? cur.filter((id) => !ids.includes(id)) : [.../* @__PURE__ */ new Set([...cur, ...ids])];
3286
+ if (next.length < min) return cur;
3287
+ return next;
3288
+ });
3289
+ const groupState = (g) => {
3290
+ const ids = groupLeaves(g).map((c) => c.id);
3291
+ const sel = ids.filter((id) => draft.includes(id)).length;
3292
+ return sel === 0 ? "none" : sel === ids.length ? "all" : "some";
3293
+ };
3294
+ const shown = open && !showFooter ? draft : selected;
3295
+ const isAll = shown.length === 0 || fullIsAll && shown.length === leafOptions.length;
3296
+ const value = isAll ? allLabel : shown.length === 1 ? leafOptions.find((o) => o.id === shown[0])?.label ?? `${shown.length} selected` : `${shown.length} selected`;
3297
+ const ql = q.trim().toLowerCase();
3298
+ const items = options.filter((o) => !ql || o.label.toLowerCase().includes(ql));
3299
+ const visibleGroups = groups ? groups.map((g) => {
3300
+ if (!ql || g.label.toLowerCase().includes(ql)) return g;
3301
+ const kids = g.children.filter((c) => c.label.toLowerCase().includes(ql));
3302
+ return kids.length ? { ...g, children: kids } : null;
3303
+ }).filter((g) => g !== null) : [];
3304
+ return /* @__PURE__ */ jsxs31("div", { className: cn("relative", fullWidth && "w-full"), ref, children: [
3305
+ /* @__PURE__ */ jsxs31(
3306
+ "button",
3307
+ {
3308
+ type: "button",
3309
+ onClick: () => open ? close() : openTray(),
3310
+ "aria-expanded": open,
3311
+ className: cn(chipTriggerClass(), fullWidth && "w-full justify-between"),
3312
+ children: [
3313
+ /* @__PURE__ */ jsx35(ChipContent, { caption, value, icon }),
3314
+ /* @__PURE__ */ jsx35(
3315
+ ChevronDown11,
3316
+ {
3317
+ size: 14,
3318
+ "aria-hidden": "true",
3319
+ className: cn("shrink-0 text-text-secondary transition-transform", open && "rotate-180")
3320
+ }
3321
+ )
3322
+ ]
3323
+ }
3324
+ ),
3325
+ open && /* @__PURE__ */ jsxs31(
3326
+ "div",
3327
+ {
3328
+ className: cn(
3329
+ "absolute top-[calc(100%+8px)] z-30 flex flex-col overflow-hidden rounded-card border border-border-default bg-surface shadow-overlay",
3330
+ menuWidthClass,
3331
+ align === "right" ? "right-0" : "left-0"
3332
+ ),
3333
+ role: "dialog",
3334
+ "aria-label": caption,
3335
+ children: [
3336
+ searchable && /* @__PURE__ */ jsx35("div", { className: "border-b border-border-default p-2", children: /* @__PURE__ */ jsxs31("div", { className: "flex h-9 items-center gap-2 rounded-control border border-border-default bg-input px-2.5", children: [
3337
+ /* @__PURE__ */ jsx35(Search5, { size: 14, className: "text-text-secondary", "aria-hidden": "true" }),
3338
+ /* @__PURE__ */ jsx35(
3339
+ "input",
3340
+ {
3341
+ type: "text",
3342
+ value: q,
3343
+ onChange: (e) => setQ(e.target.value),
3344
+ placeholder: searchPlaceholder ?? `Search ${caption.toLowerCase()}`,
3345
+ className: "h-full flex-1 bg-transparent text-[13px] outline-hidden placeholder:text-text-tertiary"
3346
+ }
3347
+ ),
3348
+ q && /* @__PURE__ */ jsx35("button", { type: "button", onClick: () => setQ(""), "aria-label": "Clear search", className: "text-text-tertiary hover:text-text-primary", children: /* @__PURE__ */ jsx35(X4, { size: 13 }) })
3349
+ ] }) }),
3350
+ /* @__PURE__ */ jsxs31("div", { className: "max-h-[280px] overflow-y-auto p-1", children: [
3351
+ groups ? visibleGroups.map((g) => {
3352
+ const state = groupState(g);
3353
+ return /* @__PURE__ */ jsxs31("div", { children: [
3354
+ /* @__PURE__ */ jsxs31(
3355
+ "button",
3356
+ {
3357
+ type: "button",
3358
+ onClick: () => toggleGroup(g),
3359
+ className: "flex w-full items-center gap-2.5 rounded-control px-2 py-2 text-left transition-colors hover:bg-subtle",
3360
+ children: [
3361
+ /* @__PURE__ */ jsx35(TriCheck, { state }),
3362
+ /* @__PURE__ */ jsx35("span", { className: cn("flex-1 text-[14px] text-text-primary", !plainParent && "font-semibold"), children: g.label })
3363
+ ]
3364
+ }
3365
+ ),
3366
+ g.children.map((c) => {
3367
+ const checked = draft.includes(c.id);
3368
+ return /* @__PURE__ */ jsxs31(
3369
+ "button",
3370
+ {
3371
+ type: "button",
3372
+ onClick: () => toggle(c.id),
3373
+ className: "flex w-full items-center gap-2.5 rounded-control py-2 pl-9 pr-2 text-left transition-colors hover:bg-subtle",
3374
+ children: [
3375
+ /* @__PURE__ */ jsx35(TriCheck, { state: checked ? "all" : "none" }),
3376
+ /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: c.label })
3377
+ ]
3378
+ },
3379
+ c.id
3380
+ );
3381
+ })
3382
+ ] }, g.id);
3383
+ }) : items.map((o) => {
3384
+ const checked = draft.includes(o.id);
3385
+ return /* @__PURE__ */ jsxs31(
3386
+ "button",
3387
+ {
3388
+ type: "button",
3389
+ onClick: () => toggle(o.id),
3390
+ className: "flex w-full items-center gap-2.5 rounded-control px-2 py-2 text-left transition-colors hover:bg-subtle",
3391
+ children: [
3392
+ /* @__PURE__ */ jsx35(
3393
+ "span",
3394
+ {
3395
+ className: cn(
3396
+ "flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-[5px] border transition-colors",
3397
+ checked ? "border-transparent bg-brand-primaryAction text-brand-onprimary" : "border-border-interactive bg-input"
3398
+ ),
3399
+ children: checked && /* @__PURE__ */ jsx35(Check7, { size: 13, strokeWidth: 3 })
3400
+ }
3401
+ ),
3402
+ /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: o.label })
3403
+ ]
3404
+ },
3405
+ o.id
3406
+ );
3407
+ }),
3408
+ (groups && !visibleGroups.length || !groups && !items.length) && /* @__PURE__ */ jsx35("div", { className: "py-6 text-center text-[13px] text-text-tertiary", children: "No matches." })
3409
+ ] }),
3410
+ showFooter ? /* @__PURE__ */ jsx35(FilterDropdownFooter, { onClear: () => setDraft(clearValue), onApply: apply }) : min === 0 && draft.length > 0 && /* @__PURE__ */ jsx35("div", { className: "border-t border-border-default p-2", children: /* @__PURE__ */ jsxs31(
3411
+ "button",
3412
+ {
3413
+ type: "button",
3414
+ onClick: () => setDraft([]),
3415
+ className: "text-[12px] font-medium text-text-link hover:underline",
3416
+ children: [
3417
+ "Clear ",
3418
+ caption.toLowerCase()
3419
+ ]
3420
+ }
3421
+ ) })
3422
+ ]
3423
+ }
3424
+ )
3425
+ ] });
3426
+ }
3427
+ function TriCheck({ state }) {
3428
+ const filled = state !== "none";
3429
+ return /* @__PURE__ */ jsxs31(
3430
+ "span",
3431
+ {
3432
+ className: cn(
3433
+ "flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-[5px] border transition-colors",
3434
+ filled ? "border-transparent bg-brand-primaryAction text-brand-onprimary" : "border-border-interactive bg-input"
3435
+ ),
3436
+ children: [
3437
+ state === "all" && /* @__PURE__ */ jsx35(Check7, { size: 13, strokeWidth: 3 }),
3438
+ state === "some" && /* @__PURE__ */ jsx35(Minus2, { size: 13, strokeWidth: 3 })
3439
+ ]
3440
+ }
3441
+ );
3442
+ }
3443
+
3444
+ // src/Toggle.tsx
3445
+ import { jsx as jsx36 } from "react/jsx-runtime";
3446
+ var SIZES2 = {
3447
+ sm: { track: "h-5 w-9", knob: "h-4 w-4", on: "translate-x-[18px]" },
3448
+ md: { track: "h-6 w-11", knob: "h-5 w-5", on: "translate-x-[22px]" }
3449
+ };
3450
+ function Toggle({ checked, onChange, label, size = "md", disabled, className }) {
3451
+ const s = SIZES2[size];
3452
+ return /* @__PURE__ */ jsx36(
3453
+ "button",
3454
+ {
3455
+ type: "button",
3456
+ role: "switch",
3457
+ "aria-checked": checked,
3458
+ "aria-label": label,
3459
+ disabled,
3460
+ onClick: () => onChange(!checked),
3461
+ className: cn(
3462
+ "relative inline-flex shrink-0 items-center rounded-full transition-colors focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-border-focus",
3463
+ s.track,
3464
+ checked ? "bg-brand-primaryAction" : "bg-border-interactive",
3465
+ disabled && "cursor-not-allowed opacity-50",
3466
+ className
3467
+ ),
3468
+ children: /* @__PURE__ */ jsx36(
3469
+ "span",
3470
+ {
3471
+ className: cn(
3472
+ "inline-block transform rounded-full bg-surface shadow-raised transition-transform",
3473
+ s.knob,
3474
+ checked ? s.on : "translate-x-0.5"
3475
+ )
3476
+ }
3477
+ )
3478
+ }
3479
+ );
3480
+ }
3481
+
3482
+ // src/AISpark.tsx
3483
+ import { useId as useId2 } from "react";
3484
+ import { Sparkles } from "lucide-react";
3485
+ import { Fragment as Fragment5, jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
3486
+ function AISpark({ size = 16, className }) {
3487
+ const id = useId2();
3488
+ return /* @__PURE__ */ jsxs32(Fragment5, { children: [
3489
+ /* @__PURE__ */ jsx37("svg", { width: "0", height: "0", "aria-hidden": "true", style: { position: "absolute" }, children: /* @__PURE__ */ jsx37("defs", { children: /* @__PURE__ */ jsxs32("linearGradient", { id, x1: "0", y1: "0", x2: "1", y2: "1", children: [
3490
+ /* @__PURE__ */ jsx37("stop", { offset: "0%", stopColor: "var(--mr-color-brand-primary)" }),
3491
+ /* @__PURE__ */ jsx37("stop", { offset: "100%", className: "[stop-color:#9474ff] in-data-[theme=dark]:[stop-color:#a488ff]" })
3492
+ ] }) }) }),
3493
+ /* @__PURE__ */ jsx37(Sparkles, { size, stroke: `url(#${id})`, className, "aria-hidden": "true" })
3494
+ ] });
3495
+ }
3496
+
3497
+ // src/Freshness.tsx
3498
+ import { jsx as jsx38 } from "react/jsx-runtime";
3499
+ var dotColor = {
3500
+ fresh: "bg-status-success",
3501
+ recent: "bg-status-warning",
3502
+ stale: "bg-text-tertiary"
3503
+ };
3504
+ var srLabel = {
3505
+ fresh: "Fresh (under 4 hours)",
3506
+ recent: "Recent (today)",
3507
+ stale: "Older than a day"
3508
+ };
3509
+ function Freshness({ level }) {
3510
+ return /* @__PURE__ */ jsx38(
3511
+ "span",
3512
+ {
3513
+ className: cn("inline-block h-1.5 w-1.5 shrink-0 rounded-full", dotColor[level]),
3514
+ role: "img",
3515
+ "aria-label": srLabel[level]
3516
+ }
3517
+ );
3518
+ }
2914
3519
  export {
3520
+ AISpark,
2915
3521
  AdvertiserNoResults,
2916
3522
  AdvertiserQuickFilter,
2917
3523
  AdvertiserSearchPrompt,
@@ -2923,10 +3529,13 @@ export {
2923
3529
  DEFAULT_SEARCH_MATCH,
2924
3530
  DataScopeFilter,
2925
3531
  DateRangeFilter,
3532
+ DateRangePicker,
2926
3533
  FilterChipBar,
2927
3534
  FilterDropdownFooter,
3535
+ Freshness,
2928
3536
  InfoTip,
2929
3537
  LineChartPlaceholder,
3538
+ MultiSelectFilter,
2930
3539
  NO_RESULTS_BODY,
2931
3540
  NO_RESULTS_TITLE,
2932
3541
  NameListModal,
@@ -2944,6 +3553,9 @@ export {
2944
3553
  SelectionPicker,
2945
3554
  SortButton,
2946
3555
  StackedColumnPlaceholder,
3556
+ TablePagination,
3557
+ Tag,
3558
+ Toggle,
2947
3559
  Tooltip,
2948
3560
  WorkspaceAvatar,
2949
3561
  WorkspaceSelectedCard,
@@ -2951,6 +3563,7 @@ export {
2951
3563
  chipTriggerClass,
2952
3564
  cycleSort,
2953
3565
  noResultsBody,
3566
+ resolveRange,
2954
3567
  sortProp
2955
3568
  };
2956
3569
  //# sourceMappingURL=index.js.map