@mediaradar/design-components 0.16.2 → 0.17.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.cjs CHANGED
@@ -65,6 +65,7 @@ __export(index_exports, {
65
65
  Tooltip: () => Tooltip,
66
66
  WorkspaceAvatar: () => WorkspaceAvatar,
67
67
  WorkspaceSelectedCard: () => WorkspaceSelectedCard,
68
+ ariaSortFor: () => ariaSortFor,
68
69
  buttonVariants: () => buttonVariants,
69
70
  chipTriggerClass: () => chipTriggerClass,
70
71
  cycleSort: () => cycleSort,
@@ -3099,7 +3100,22 @@ function Chip({
3099
3100
  // src/SortButton.tsx
3100
3101
  var import_lucide_react18 = require("lucide-react");
3101
3102
  var import_jsx_runtime31 = require("react/jsx-runtime");
3102
- function SortButton({ label, sortKey, sort, onSort, disabled = false }) {
3103
+ var ALIGN = {
3104
+ left: "justify-start text-left",
3105
+ center: "justify-center text-center",
3106
+ right: "justify-end text-right"
3107
+ };
3108
+ function SortButton({
3109
+ label,
3110
+ sortKey,
3111
+ sort,
3112
+ onSort,
3113
+ disabled = false,
3114
+ sortable = true,
3115
+ align = "left",
3116
+ testIdPrefix
3117
+ }) {
3118
+ if (!sortable) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("inline-flex", ALIGN[align]), children: label });
3103
3119
  const active = !disabled && sort.key === sortKey;
3104
3120
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
3105
3121
  "button",
@@ -3107,9 +3123,9 @@ function SortButton({ label, sortKey, sort, onSort, disabled = false }) {
3107
3123
  type: "button",
3108
3124
  disabled,
3109
3125
  onClick: () => onSort(sortKey),
3110
- "aria-sort": active ? sort.dir === "asc" ? "ascending" : "descending" : "none",
3126
+ "data-testid": testIdPrefix && `${testIdPrefix}-sort-${sortKey}`,
3111
3127
  className: cn(
3112
- // text-left overrides the UA default on <button>, which would centre a
3128
+ // ALIGN's text-* overrides the UA default on <button>, which would centre a
3113
3129
  // label that wraps onto two lines, out of step with the column under it.
3114
3130
  // `uppercase` is NOT this control imposing a treatment -- it is
3115
3131
  // restoring one. Every table header row sets uppercase on the <tr>,
@@ -3124,15 +3140,17 @@ function SortButton({ label, sortKey, sort, onSort, disabled = false }) {
3124
3140
  // subtly tighter than the fixed headers next to them. A control
3125
3141
  // should carry exactly the properties that do not inherit, and
3126
3142
  // nothing more.
3127
- "group inline-flex items-center gap-1 text-left uppercase transition-colors",
3143
+ "group inline-flex items-center gap-1 uppercase transition-colors",
3144
+ ALIGN[align],
3128
3145
  !disabled && "hover:text-text-primary"
3129
3146
  ),
3130
3147
  children: [
3131
3148
  label,
3132
- !disabled && (active ? sort.dir === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react18.ArrowUp, { size: 12, className: "shrink-0 text-brand-primaryAction" }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react18.ArrowDown, { size: 12, className: "shrink-0 text-brand-primaryAction" }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3149
+ !disabled && (active ? sort.dir === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react18.ArrowUp, { size: 12, "aria-hidden": "true", className: "shrink-0 text-brand-primaryAction" }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react18.ArrowDown, { size: 12, "aria-hidden": "true", className: "shrink-0 text-brand-primaryAction" }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3133
3150
  import_lucide_react18.ArrowUpDown,
3134
3151
  {
3135
3152
  size: 12,
3153
+ "aria-hidden": "true",
3136
3154
  className: "shrink-0 text-text-tertiary opacity-50 transition-opacity group-hover:opacity-100"
3137
3155
  }
3138
3156
  ))
@@ -3150,6 +3168,10 @@ function cycleSort(current, key, firstDir = "desc") {
3150
3168
  function sortProp(sort) {
3151
3169
  return sort ?? { key: null, dir: "desc" };
3152
3170
  }
3171
+ function ariaSortFor(sort, key) {
3172
+ if (!sort || sort.key !== key) return void 0;
3173
+ return sort.dir === "asc" ? "ascending" : "descending";
3174
+ }
3153
3175
 
3154
3176
  // src/Pager.tsx
3155
3177
  var import_lucide_react19 = require("lucide-react");
@@ -3273,7 +3295,8 @@ function TablePagination({
3273
3295
  onPerPageChange,
3274
3296
  perPageOptions = [25, 50, 100],
3275
3297
  itemLabel = "results",
3276
- className
3298
+ className,
3299
+ testIdPrefix
3277
3300
  }) {
3278
3301
  const totalPages = Math.max(1, Math.ceil(totalItems / perPage));
3279
3302
  const current = Math.min(page, totalPages);
@@ -3284,7 +3307,7 @@ function TablePagination({
3284
3307
  btn,
3285
3308
  "text-text-secondary hover:bg-subtle hover:text-text-primary disabled:pointer-events-none disabled:opacity-30"
3286
3309
  );
3287
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: cn("flex flex-wrap items-center justify-between gap-x-4 gap-y-2", className), children: [
3310
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: cn("flex flex-wrap items-center justify-between gap-x-4 gap-y-2", className), "data-testid": testIdPrefix, children: [
3288
3311
  /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-text-secondary", children: [
3289
3312
  /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "relative", children: [
3290
3313
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
@@ -3293,6 +3316,7 @@ function TablePagination({
3293
3316
  value: perPage,
3294
3317
  onChange: (e) => onPerPageChange(Number(e.target.value)),
3295
3318
  "aria-label": "Items per page",
3319
+ "data-testid": testIdPrefix && `${testIdPrefix}-per-page`,
3296
3320
  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",
3297
3321
  children: perPageOptions.map((n) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("option", { value: n, children: n }, n))
3298
3322
  }
@@ -3316,6 +3340,7 @@ function TablePagination({
3316
3340
  onClick: () => onPageChange(1),
3317
3341
  disabled: current === 1,
3318
3342
  "aria-label": "First page",
3343
+ "data-testid": testIdPrefix && `${testIdPrefix}-first`,
3319
3344
  className: stepBtn,
3320
3345
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronFirst, { size: 16, "aria-hidden": "true" })
3321
3346
  }
@@ -3327,6 +3352,7 @@ function TablePagination({
3327
3352
  onClick: () => onPageChange(current - 1),
3328
3353
  disabled: current === 1,
3329
3354
  "aria-label": "Previous page",
3355
+ "data-testid": testIdPrefix && `${testIdPrefix}-prev`,
3330
3356
  className: stepBtn,
3331
3357
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronLeft, { size: 16, "aria-hidden": "true" })
3332
3358
  }
@@ -3336,6 +3362,7 @@ function TablePagination({
3336
3362
  "button",
3337
3363
  {
3338
3364
  type: "button",
3365
+ "data-testid": testIdPrefix && `${testIdPrefix}-page-${p}`,
3339
3366
  onClick: () => onPageChange(p),
3340
3367
  "aria-current": p === current ? "page" : void 0,
3341
3368
  className: cn(
@@ -3354,6 +3381,7 @@ function TablePagination({
3354
3381
  onClick: () => onPageChange(current + 1),
3355
3382
  disabled: current === totalPages,
3356
3383
  "aria-label": "Next page",
3384
+ "data-testid": testIdPrefix && `${testIdPrefix}-next`,
3357
3385
  className: stepBtn,
3358
3386
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronRight, { size: 16, "aria-hidden": "true" })
3359
3387
  }
@@ -3365,6 +3393,7 @@ function TablePagination({
3365
3393
  onClick: () => onPageChange(totalPages),
3366
3394
  disabled: current === totalPages,
3367
3395
  "aria-label": "Last page",
3396
+ "data-testid": testIdPrefix && `${testIdPrefix}-last`,
3368
3397
  className: stepBtn,
3369
3398
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronLast, { size: 16, "aria-hidden": "true" })
3370
3399
  }
@@ -3806,7 +3835,7 @@ var SIZES2 = {
3806
3835
  sm: { track: "h-5 w-9", knob: "h-4 w-4", on: "translate-x-[18px]" },
3807
3836
  md: { track: "h-6 w-11", knob: "h-5 w-5", on: "translate-x-[22px]" }
3808
3837
  };
3809
- function Toggle({ checked, onChange, label, size = "md", disabled, className }) {
3838
+ function Toggle({ checked, onChange, label, size = "md", disabled, className, testIdPrefix }) {
3810
3839
  const s = SIZES2[size];
3811
3840
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3812
3841
  "button",
@@ -3816,6 +3845,7 @@ function Toggle({ checked, onChange, label, size = "md", disabled, className })
3816
3845
  "aria-checked": checked,
3817
3846
  "aria-label": label,
3818
3847
  disabled,
3848
+ "data-testid": testIdPrefix && `${testIdPrefix}-toggle`,
3819
3849
  onClick: () => onChange(!checked),
3820
3850
  className: cn(
3821
3851
  "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",
@@ -3922,6 +3952,7 @@ function Freshness({ level }) {
3922
3952
  Tooltip,
3923
3953
  WorkspaceAvatar,
3924
3954
  WorkspaceSelectedCard,
3955
+ ariaSortFor,
3925
3956
  buttonVariants,
3926
3957
  chipTriggerClass,
3927
3958
  cycleSort,