@jirawatpyk/aura-react 5.68.0 → 5.70.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.
@@ -1,8 +1,19 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { Button } from "./Button.js";
4
- import { cx } from "./internal.js";
4
+ import { cx, devWarnOnce, fixedTrapped } from "./internal.js";
5
5
  import { useStrings } from "./locale.js";
6
+ const HEIGHT = "--aura-actionbar-height";
7
+ const edges = [];
8
+ function writeHeight() {
9
+ const root = document.documentElement;
10
+ for (let i = edges.length - 1; i >= 0; i--)
11
+ if (getComputedStyle(edges[i]).position === "fixed") {
12
+ root.style.setProperty(HEIGHT, edges[i].offsetHeight + "px");
13
+ return;
14
+ }
15
+ root.style.removeProperty(HEIGHT);
16
+ }
6
17
  const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
7
18
  const t = useStrings();
8
19
  const bulk = props.selected != null;
@@ -13,6 +24,40 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
13
24
  });
14
25
  const cameFrom = React.useRef(null);
15
26
  const own = React.useRef(null);
27
+ const viewport = (props.position || "viewport") === "viewport";
28
+ const edge = !viewport ? null : props.look === "edge" ? "all" : props.edgeBelow || null;
29
+ if (props.look === "edge" && props.edgeBelow && viewport)
30
+ devWarnOnce(
31
+ "actionbar-edge-both",
32
+ 'ActionBar: look="edge" draws the edge strip at every width, so edgeBelow does nothing. Pass edgeBelow alone for a strip on a phone and the floating card above it.'
33
+ );
34
+ React.useEffect(
35
+ function() {
36
+ const el = own.current;
37
+ if (!edge || !el) return;
38
+ let checked = false;
39
+ function sync() {
40
+ writeHeight();
41
+ if (!checked && getComputedStyle(el).position === "fixed" && (checked = true, fixedTrapped(el)))
42
+ devWarnOnce(
43
+ "actionbar-edge-trapped",
44
+ `ActionBar look="edge": an ancestor has a transform, filter, will-change or paint containment, so the fixed strip is placed against it instead of the screen. Remove it from the bar's ancestors.`
45
+ );
46
+ }
47
+ edges.push(el);
48
+ const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
49
+ if (ro) ro.observe(el, { box: "border-box" });
50
+ window.addEventListener("resize", sync);
51
+ sync();
52
+ return function() {
53
+ if (ro) ro.disconnect();
54
+ window.removeEventListener("resize", sync);
55
+ edges.splice(edges.indexOf(el), 1);
56
+ writeHeight();
57
+ };
58
+ },
59
+ [edge, idle]
60
+ );
16
61
  function clear() {
17
62
  props.onClearSelection();
18
63
  setTimeout(function() {
@@ -39,6 +84,7 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
39
84
  className: cx(
40
85
  "aura-actionbar",
41
86
  "aura-actionbar--" + (props.position || "viewport"),
87
+ edge && (edge === "all" ? "aura-actionbar--edge" : "aura-actionbar--edge-below-" + edge),
42
88
  idle && "is-idle",
43
89
  props.className
44
90
  )
@@ -8,6 +8,8 @@ import { IconLoaderCircle } from "./icons.js";
8
8
  function ButtonLink(props, ref, Link) {
9
9
  const variant = props.variant || "primary";
10
10
  const disabled = !!props.disabled;
11
+ const ad = props["aria-disabled"];
12
+ const gated = !disabled && (ad === true || ad === "true");
11
13
  const rest = omit(props, [
12
14
  "variant",
13
15
  "className",
@@ -29,7 +31,7 @@ function ButtonLink(props, ref, Link) {
29
31
  ref,
30
32
  href: disabled ? void 0 : props.href,
31
33
  role: disabled ? "link" : void 0,
32
- "aria-disabled": disabled || void 0,
34
+ "aria-disabled": disabled || gated || void 0,
33
35
  tabIndex: disabled ? -1 : props.tabIndex,
34
36
  className: buttonClass({
35
37
  variant,
@@ -38,7 +40,9 @@ function ButtonLink(props, ref, Link) {
38
40
  touchHeight: props.touchHeight,
39
41
  className: props.className
40
42
  }),
41
- onClick: disabled ? void 0 : props.onClick
43
+ onClick: disabled ? void 0 : gated ? function(e) {
44
+ e.preventDefault();
45
+ } : props.onClick
42
46
  },
43
47
  props.icon ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon }) : null,
44
48
  props.children,
@@ -56,6 +60,8 @@ const Button = React.forwardRef(
56
60
  const loading = !!props.loading;
57
61
  const ad = props["aria-disabled"];
58
62
  const blocked = loading || ad === true || ad === "true";
63
+ const ab = props["aria-busy"];
64
+ const busy = loading || ab === true || ab === "true";
59
65
  const rest = omit(props, [
60
66
  "variant",
61
67
  "className",
@@ -83,7 +89,7 @@ const Button = React.forwardRef(
83
89
  loading,
84
90
  className: props.className
85
91
  }),
86
- "aria-busy": loading || void 0,
92
+ "aria-busy": busy || void 0,
87
93
  "aria-disabled": blocked || void 0,
88
94
  onClick: blocked ? function(e) {
89
95
  e.preventDefault();
@@ -5,8 +5,10 @@ import { useStrings } from "./locale.js";
5
5
  import { Icon } from "./Icon.js";
6
6
  import { IconButton } from "./IconButton.js";
7
7
  import { Field } from "./Field.js";
8
+ import { Button } from "./Button.js";
9
+ import { Progress } from "./Progress.js";
8
10
  import { formatBytes } from "./text.js";
9
- import { IconCircleAlert, IconCircleCheck, IconCloudUpload, IconFile, IconImage, IconX } from "./icons.js";
11
+ import { IconCircleAlert, IconCircleCheck, IconCloudUpload, IconFile, IconImage, IconUpload, IconX } from "./icons.js";
10
12
  function matches(file, accept) {
11
13
  if (!accept) return true;
12
14
  const name = (file.name || "").toLowerCase(), type = (file.type || "").toLowerCase();
@@ -40,6 +42,22 @@ const FileUpload = React.forwardRef(function FileUpload2(props, ref) {
40
42
  const urls = React.useRef({});
41
43
  const maxFiles = props.multiple ? props.maxFiles : 1;
42
44
  const note = t.accepts(describeAccept(props.accept, t), props.maxSize ? formatBytes(props.maxSize) : "");
45
+ const pickState = React.useState(null);
46
+ const buttonRef = React.useRef(null);
47
+ const buttonMode = props.variant === "button";
48
+ React.useEffect(
49
+ function() {
50
+ const el = inputRef.current;
51
+ if (!buttonMode || !el) return;
52
+ el.focus = function(o) {
53
+ if (buttonRef.current) buttonRef.current.focus(o);
54
+ };
55
+ return function() {
56
+ delete el.focus;
57
+ };
58
+ },
59
+ [buttonMode]
60
+ );
43
61
  React.useEffect(function() {
44
62
  return function() {
45
63
  Object.keys(urls.current).forEach(function(k) {
@@ -107,6 +125,95 @@ const FileUpload = React.forwardRef(function FileUpload2(props, ref) {
107
125
  if (inputRef.current) inputRef.current.focus();
108
126
  }
109
127
  const error = props.error;
128
+ if (props.variant === "button") {
129
+ const err = error || pickState[0];
130
+ const desc = [err ? id + "-error" : props.hint ? id + "-hint" : null, note ? id + "-note" : null].filter(Boolean).join(" ") || void 0;
131
+ return /* @__PURE__ */ React.createElement(
132
+ Field,
133
+ {
134
+ id,
135
+ label: props.label,
136
+ labelAs: "span",
137
+ labelId: id + "-label",
138
+ hint: props.hint,
139
+ error: err,
140
+ required: props.required,
141
+ optional: props.optional,
142
+ disabled: props.disabled,
143
+ className: cx("aura-upload-field", props.className)
144
+ },
145
+ /* @__PURE__ */ React.createElement("div", { className: "aura-upload-button" }, /* @__PURE__ */ React.createElement(
146
+ Button,
147
+ {
148
+ ref: buttonRef,
149
+ id: id + "-button",
150
+ variant: "secondary",
151
+ icon: /* @__PURE__ */ React.createElement(IconUpload, null),
152
+ touchHeight: props.touchHeight,
153
+ disabled: props.disabled,
154
+ "aria-labelledby": props.label ? id + "-label " + id + "-button" : void 0,
155
+ "aria-describedby": desc,
156
+ onClick: function() {
157
+ if (inputRef.current) inputRef.current.click();
158
+ }
159
+ },
160
+ props.buttonLabel != null ? props.buttonLabel : props.multiple ? t.browse : t.browseOne
161
+ ), /* @__PURE__ */ React.createElement(
162
+ "input",
163
+ {
164
+ ref: inputMerged,
165
+ id,
166
+ type: "file",
167
+ className: "aura-upload__input",
168
+ tabIndex: -1,
169
+ "aria-hidden": true,
170
+ accept: props.accept,
171
+ multiple: !!props.multiple,
172
+ disabled: props.disabled,
173
+ name: props.name,
174
+ required: props.name ? props.required : void 0,
175
+ onInvalid: function(e) {
176
+ e.preventDefault();
177
+ pickState[1](props.multiple ? t.browse : t.browseOne);
178
+ if (buttonRef.current) buttonRef.current.focus();
179
+ },
180
+ onChange: function(e) {
181
+ const files = Array.prototype.slice.call(e.target.files || []);
182
+ if (!files.length) return;
183
+ let refused = null;
184
+ const ok = files.filter(function(f) {
185
+ const why = !matches(f, props.accept) ? t.fileWrongType : props.maxSize && f.size > props.maxSize ? t.fileTooBig(formatBytes(props.maxSize)) : null;
186
+ if (why && !refused) refused = why;
187
+ return !why;
188
+ });
189
+ pickState[1](refused);
190
+ if (!props.name) e.target.value = "";
191
+ else if (refused) {
192
+ try {
193
+ const dt = new DataTransfer();
194
+ ok.forEach(function(f) {
195
+ dt.items.add(f);
196
+ });
197
+ e.target.files = dt.files;
198
+ } catch (x) {
199
+ e.target.value = "";
200
+ }
201
+ }
202
+ if (ok.length && props.onSelect) props.onSelect(ok);
203
+ }
204
+ }
205
+ ), note ? /* @__PURE__ */ React.createElement("span", { className: "aura-upload__note", id: id + "-note" }, note) : null),
206
+ props.progress !== void 0 ? /* @__PURE__ */ React.createElement(
207
+ Progress,
208
+ {
209
+ className: "aura-upload-button__progress",
210
+ size: "sm",
211
+ value: props.progress == null ? void 0 : props.progress,
212
+ label: t.uploading
213
+ }
214
+ ) : null
215
+ );
216
+ }
110
217
  return /* @__PURE__ */ React.createElement(
111
218
  Field,
112
219
  {
@@ -7,6 +7,8 @@ const IconButton = React.forwardRef(function IconButton2(props, ref) {
7
7
  const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
8
8
  useAutoTip();
9
9
  const own = props.title !== void 0;
10
+ const ad = props["aria-disabled"];
11
+ const blocked = ad === true || ad === "true";
10
12
  return /* @__PURE__ */ React.createElement(
11
13
  "button",
12
14
  {
@@ -16,6 +18,9 @@ const IconButton = React.forwardRef(function IconButton2(props, ref) {
16
18
  "aria-label": props.label,
17
19
  "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
18
20
  "data-aura-tip": own ? void 0 : props.label,
21
+ onClick: blocked ? function(e) {
22
+ e.preventDefault();
23
+ } : props.onClick,
19
24
  className: cx(
20
25
  "aura-icon-btn",
21
26
  props.tone === "danger" && "aura-icon-btn--danger",
@@ -1,17 +1,9 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { PageHeader as StaticPageHeader } from "./PageHeader.js";
4
- import { devWarnOnce, useMergedRef } from "./internal.js";
4
+ import { devWarnOnce, fixedTrapped as trapped, useMergedRef } from "./internal.js";
5
5
  const NAME = "--aura-page-actions-height";
6
6
  const bars = [];
7
- function trapped(el) {
8
- for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
9
- const s = getComputedStyle(p);
10
- if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
11
- return true;
12
- }
13
- return false;
14
- }
15
7
  const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
16
8
  const own = React.useRef(null);
17
9
  const merged = useMergedRef(ref, own);
@@ -25,9 +25,56 @@ function pageList(page, count, sib) {
25
25
  if (count > 1) out.push(count);
26
26
  return out;
27
27
  }
28
- const Pagination = React.forwardRef(function Pagination2(props, ref) {
28
+ function cursorNav(props, ref, Link, t) {
29
+ const links = props.firstHref != null || props.previousHref != null || props.nextHref != null;
30
+ function step(key, href, on, has, label, rel, icon, after) {
31
+ const body = /* @__PURE__ */ React.createElement(React.Fragment, null, icon && !after ? /* @__PURE__ */ React.createElement(Icon, { name: icon, size: "sm" }) : null, /* @__PURE__ */ React.createElement("span", null, label), icon && after ? /* @__PURE__ */ React.createElement(Icon, { name: icon, size: "sm" }) : null);
32
+ const cls = "aura-page aura-page--step";
33
+ if (has === false || !href && !on)
34
+ return links ? /* @__PURE__ */ React.createElement("span", { key, className: cls, role: "link", "aria-disabled": true }, body) : /* @__PURE__ */ React.createElement("button", { key, type: "button", className: cls, disabled: true }, body);
35
+ if (href != null)
36
+ return /* @__PURE__ */ React.createElement(
37
+ Link,
38
+ {
39
+ key,
40
+ href,
41
+ rel,
42
+ className: cls,
43
+ onClick: function(e) {
44
+ if (on && plainClick(e)) {
45
+ e.preventDefault();
46
+ on();
47
+ }
48
+ }
49
+ },
50
+ body
51
+ );
52
+ return /* @__PURE__ */ React.createElement("button", { key, type: "button", className: cls, onClick: on }, body);
53
+ }
54
+ return /* @__PURE__ */ React.createElement(
55
+ "nav",
56
+ {
57
+ ref,
58
+ className: cx("aura-pagination", "aura-pagination--cursor", props.className),
59
+ "aria-label": props.label || t.pagination
60
+ },
61
+ props.status != null && props.status !== false && props.status !== "" ? /* @__PURE__ */ React.createElement("span", { className: "aura-pagination__status" }, props.status) : null,
62
+ /* @__PURE__ */ React.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), step(
63
+ "prev",
64
+ props.previousHref,
65
+ props.onPrevious,
66
+ props.hasPrevious,
67
+ t.prevPage,
68
+ "prev",
69
+ /* @__PURE__ */ React.createElement(IconChevronLeft, null),
70
+ false
71
+ ), step("next", props.nextHref, props.onNext, props.hasNext, t.nextPage, "next", /* @__PURE__ */ React.createElement(IconChevronRight, null), true))
72
+ );
73
+ }
74
+ const Pagination = React.forwardRef(function Pagination2(all, ref) {
29
75
  const t = useStrings();
30
76
  useAutoTip();
77
+ const props = all;
31
78
  const count = Math.max(1, props.pageCount || 1);
32
79
  const st = useMaybeControlled(props.page, props.defaultPage || 1, props.onChange);
33
80
  const page = Math.min(count, Math.max(1, st[0]));
@@ -36,6 +83,7 @@ const Pagination = React.forwardRef(function Pagination2(props, ref) {
36
83
  }
37
84
  const link = props.getHref;
38
85
  const Link = useLinkComponent(props.linkComponent);
86
+ if (all.mode === "cursor") return cursorNav(all, ref, Link, t);
39
87
  function item(p, label, extra) {
40
88
  const common = Object.assign(
41
89
  {
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { spinnerElement } from "./display.js";
4
+ const Spinner = React.forwardRef(function Spinner2(props, ref) {
5
+ return spinnerElement(props, ref);
6
+ });
7
+ export {
8
+ Spinner
9
+ };
package/dist/esm/Table.js CHANGED
@@ -1,7 +1,9 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { cx, devWarnOnce, uid, useIsoLayoutEffect } from "./internal.js";
4
- import { useDensity } from "./locale.js";
4
+ import { useDensity, useLinkComponent } from "./locale.js";
5
+ import { Icon } from "./Icon.js";
6
+ import { IconArrowDown, IconArrowUp, IconArrowUpDown } from "./icons.js";
5
7
  import { inertProps, skeletonBody, skeletonColgroup } from "./TableSkeleton.js";
6
8
  const StackLabels = React.createContext(null);
7
9
  const ColumnIndex = React.createContext(-1);
@@ -242,8 +244,39 @@ function cellClass(base, p) {
242
244
  );
243
245
  }
244
246
  const Th = React.forwardRef(function Th2(props, ref) {
245
- const { align, numeric, mono, className, scope, label, card, skeleton, skeletonWidth, wrap, ...rest } = props;
247
+ const {
248
+ align,
249
+ numeric,
250
+ mono,
251
+ className,
252
+ scope,
253
+ label,
254
+ card,
255
+ skeleton,
256
+ skeletonWidth,
257
+ wrap,
258
+ sort,
259
+ onSort,
260
+ sortHref,
261
+ linkComponent,
262
+ ...rest
263
+ } = props;
246
264
  const stacked = React.useContext(StackLabels) != null;
265
+ const Link = useLinkComponent(linkComponent);
266
+ const sortable = !!onSort || sortHref != null;
267
+ const ariaSort = sort || (sortable ? "none" : void 0);
268
+ let children = props.children;
269
+ if (sortable) {
270
+ const icon = /* @__PURE__ */ React.createElement(
271
+ Icon,
272
+ {
273
+ name: sort === "ascending" ? /* @__PURE__ */ React.createElement(IconArrowUp, null) : sort === "descending" ? /* @__PURE__ */ React.createElement(IconArrowDown, null) : /* @__PURE__ */ React.createElement(IconArrowUpDown, null),
274
+ size: 12
275
+ }
276
+ );
277
+ const cls = cx("aura-table__sort", sort && sort !== "none" && "is-active");
278
+ children = sortHref != null ? /* @__PURE__ */ React.createElement(Link, { href: sortHref, className: cls }, props.children, icon) : /* @__PURE__ */ React.createElement("button", { type: "button", className: cls, onClick: onSort }, props.children, icon);
279
+ }
247
280
  return /* @__PURE__ */ React.createElement(
248
281
  "th",
249
282
  {
@@ -252,8 +285,10 @@ const Th = React.forwardRef(function Th2(props, ref) {
252
285
  className: cellClass("aura-tbl__th", props),
253
286
  role: stacked ? scope === "row" ? "rowheader" : "columnheader" : void 0,
254
287
  "data-card": stacked && (card === "title" || card === "action") ? card : void 0,
288
+ "aria-sort": ariaSort,
255
289
  ...rest
256
- }
290
+ },
291
+ children
257
292
  );
258
293
  });
259
294
  const Td = React.forwardRef(function Td2(props, ref) {
@@ -11,6 +11,7 @@ import {
11
11
  IconCircleDotDashed,
12
12
  IconInbox,
13
13
  IconInfo,
14
+ IconLoaderCircle,
14
15
  IconMinus,
15
16
  IconTrendingDown,
16
17
  IconTrendingUp,
@@ -101,7 +102,7 @@ const PILL_ICON = {
101
102
  };
102
103
  function statusPillElement(props, ref) {
103
104
  const tone = props.tone || toneFor(props.children);
104
- const rest = omit(props, ["tone", "className", "children", "wrap"]);
105
+ const rest = omit(props, ["tone", "className", "children", "wrap", "busy"]);
105
106
  return /* @__PURE__ */ React.createElement(
106
107
  "span",
107
108
  {
@@ -109,10 +110,26 @@ function statusPillElement(props, ref) {
109
110
  ref,
110
111
  className: cx("aura-pill", "aura-pill--" + tone, props.wrap && "is-wrap", props.className)
111
112
  },
112
- /* @__PURE__ */ React.createElement(Icon, { name: h(PILL_ICON[tone] || IconCircle), size: 12 }),
113
+ props.busy ? /* @__PURE__ */ React.createElement(Icon, { name: h(IconLoaderCircle), size: 12, className: "aura-spin" }) : /* @__PURE__ */ React.createElement(Icon, { name: h(PILL_ICON[tone] || IconCircle), size: 12 }),
113
114
  props.wrap ? /* @__PURE__ */ React.createElement("span", { className: "aura-pill__text" }, props.children) : props.children
114
115
  );
115
116
  }
117
+ function spinnerElement(props, ref) {
118
+ const rest = omit(props, ["size", "label", "className"]);
119
+ const label = props.label;
120
+ return /* @__PURE__ */ React.createElement(
121
+ "span",
122
+ {
123
+ ...rest,
124
+ ref,
125
+ className: cx("aura-spinner", "aura-spinner--" + (props.size || "md"), props.className),
126
+ role: label ? "status" : void 0,
127
+ "aria-hidden": label ? void 0 : true
128
+ },
129
+ /* @__PURE__ */ React.createElement(Icon, { name: h(IconLoaderCircle), size: props.size || "md", className: "aura-spin" }),
130
+ label ? /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only" }, label) : null
131
+ );
132
+ }
116
133
  function badgeElement(props, ref) {
117
134
  const rest = omit(props, ["tone", "variant", "icon", "className", "children"]);
118
135
  return /* @__PURE__ */ React.createElement(
@@ -273,6 +290,9 @@ function ServerCard(props) {
273
290
  function ServerStatusPill(props) {
274
291
  return statusPillElement(props, void 0);
275
292
  }
293
+ function ServerSpinner(props) {
294
+ return spinnerElement(props, void 0);
295
+ }
276
296
  function ServerBadge(props) {
277
297
  return badgeElement(props, void 0);
278
298
  }
@@ -292,6 +312,7 @@ export {
292
312
  ServerBadge,
293
313
  ServerCard,
294
314
  ServerEmptyState,
315
+ ServerSpinner,
295
316
  ServerStat,
296
317
  ServerStatusPill,
297
318
  alertElement,
@@ -301,6 +322,7 @@ export {
301
322
  cardElement,
302
323
  emptyStateElement,
303
324
  linkClass,
325
+ spinnerElement,
304
326
  statElement,
305
327
  statusPillElement
306
328
  };
package/dist/esm/index.js CHANGED
@@ -60,6 +60,7 @@ import { Progress } from "./Progress.js";
60
60
  import { Skeleton } from "./Skeleton.js";
61
61
  import { EmptyState } from "./EmptyState.js";
62
62
  import { Pagination } from "./Pagination.js";
63
+ import { Spinner } from "./Spinner.js";
63
64
  import { Accordion } from "./Accordion.js";
64
65
  import { Popover } from "./Popover.js";
65
66
  import { NumberField } from "./NumberField.js";
@@ -117,6 +118,7 @@ export {
117
118
  SideNav,
118
119
  Skeleton,
119
120
  Sparkline,
121
+ Spinner,
120
122
  Stack,
121
123
  Stat,
122
124
  StatusPill,
@@ -109,6 +109,14 @@ function plainClick(e) {
109
109
  return !e.defaultPrevented && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
110
110
  }
111
111
  const FilterSheet = React.createContext(false);
112
+ function fixedTrapped(el) {
113
+ for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
114
+ const s = getComputedStyle(p);
115
+ if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
116
+ return true;
117
+ }
118
+ return false;
119
+ }
112
120
  export {
113
121
  FOCUSABLE,
114
122
  FilterSheet,
@@ -117,6 +125,7 @@ export {
117
125
  compare,
118
126
  cx,
119
127
  devWarnOnce,
128
+ fixedTrapped,
120
129
  focusFirst,
121
130
  inClosedDetails,
122
131
  isTabStop,
@@ -134,6 +134,7 @@ const STRINGS = {
134
134
  statusUnknown: "No data",
135
135
  opensInNewTab: "opens in a new tab",
136
136
  required: "required",
137
+ firstPage: "First page",
137
138
  filtersApplied: function(n2) {
138
139
  return "Filters, " + n2.toLocaleString("en") + " applied";
139
140
  },
@@ -130,6 +130,7 @@ const sv = {
130
130
  statusUnknown: "Ingen data",
131
131
  opensInNewTab: "\xF6ppnas i en ny flik",
132
132
  required: "obligatoriskt",
133
+ firstPage: "F\xF6rsta sidan",
133
134
  filtersApplied: function(n) {
134
135
  return "Filter, " + n.toLocaleString("sv-SE") + " aktiva";
135
136
  },
@@ -130,6 +130,7 @@ const th = {
130
130
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
131
131
  opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
132
132
  required: "\u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19",
133
+ firstPage: "\u0E2B\u0E19\u0E49\u0E32\u0E41\u0E23\u0E01",
133
134
  filtersApplied: function(n2) {
134
135
  return "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07, \u0E43\u0E0A\u0E49\u0E2D\u0E22\u0E39\u0E48 " + n2.toLocaleString("en") + " \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
135
136
  },