@hortiview/shared-components 2.7.0 → 2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## [2.8.0](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.7.0...v2.8.0) (2025-10-28)
2
+
3
+ ### Features
4
+
5
+ * add SafeForm component to prevent accidental submissions and update related components ([edcef25](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/edcef25688a9cde175feb1307639d742c020f4fe))
6
+
7
+ ### Bug Fixes
8
+
9
+ * allow onClick methods of submit buttons to be executed ([cc0f7df](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/cc0f7df87faf7647a336d1e07ba3d54630bcf24d))
10
+ * ensure button type is explicitly set in SearchBar component to avoid unindented submit ([1772631](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/17726319501bf5111dccb2bbb862e9968ee75aa7))
11
+
12
+ ### Documentation
13
+
14
+ * update README to specify date and time formats from Time.ts ([a29a632](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/a29a632660dedf95241ab6c467cf95d1bafef385))
15
+
16
+ ### Code Refactoring
17
+
18
+ * reorder SafeForm export in main.ts for faster lookup ([5935b7b](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/5935b7bebb4e970946d7f499c0b70db4f4b123c2))
19
+
1
20
  ## [2.7.0](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.6.1...v2.7.0) (2025-10-24)
2
21
 
3
22
  ### Features
package/README.md CHANGED
@@ -54,6 +54,7 @@ Additionally the library provides form components using [react-hook-form](https:
54
54
  1. [OfflineView](#offlineview)
55
55
  1. [OnboardingBanner](#onboardingbanner)
56
56
  1. [OverflowTooltip](#overflowtooltip)
57
+ 1. [SafeForm](#safeform)
57
58
  1. [ScrollBar](#scrollbar)
58
59
  1. [SearchBar](#searchbar)
59
60
  1. [Select](#select)
@@ -358,14 +359,14 @@ const formMethods = useForm<{ check: boolean }>({
358
359
  const { handleSubmit } = formMethods;
359
360
 
360
361
  <FormProvider {...formMethods}>
361
- <form onSubmit={handleSubmit(onSubmit)}>
362
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
362
363
  <FormCheckBox<{ check: boolean }>
363
364
  propertyName={`check`}
364
365
  label={'My Checkbox'}
365
366
  onChange={() => additionalOnChange()}
366
367
  validate={validateFn}
367
368
  />
368
- </form>
369
+ </SafeForm>
369
370
  </FormProvider>;
370
371
  ```
371
372
 
@@ -384,13 +385,13 @@ const formMethods = useForm<{ birthday: string }>({
384
385
  const { handleSubmit } = formMethods;
385
386
 
386
387
  <FormProvider {...formMethods}>
387
- <form onSubmit={handleSubmit(onSubmit)}>
388
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
388
389
  <FormDatePicker<{ birthday: string }>
389
390
  propertyName={'birthday'}
390
391
  label={'user.date-of-birth'}
391
392
  maxRangeYear={0}
392
393
  />
393
- </form>
394
+ </SafeForm>
394
395
  </FormProvider>;
395
396
  ```
396
397
 
@@ -409,7 +410,7 @@ const formMethods = useForm<{ birthday: string }>({
409
410
  const { handleSubmit } = formMethods;
410
411
 
411
412
  <FormProvider {...formMethods}>
412
- <form onSubmit={handleSubmit(onSubmit)}>
413
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
413
414
  <FormNumber<{ price: number }>
414
415
  propertyName='price'
415
416
  label='module.price'
@@ -420,7 +421,7 @@ const { handleSubmit } = formMethods;
420
421
  allowLeadingZeros={false}
421
422
  prefix=" €"
422
423
  />
423
- </form>
424
+ </SafeForm>
424
425
  </FormProvider>;
425
426
  ```
426
427
 
@@ -439,7 +440,7 @@ const formMethods = useForm<{ radioValue: string }>({
439
440
  const { handleSubmit } = formMethods;
440
441
 
441
442
  <FormProvider {...formMethods}>
442
- <form onSubmit={handleSubmit(onSubmit)}>
443
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
443
444
  <FormRadio<{ radioValue: string }>
444
445
  propertyName='radioValue'
445
446
  options={[
@@ -447,7 +448,7 @@ const { handleSubmit } = formMethods;
447
448
  { value: 'free', label: 'Free },
448
449
  ]}
449
450
  />
450
- </form>
451
+ </SafeForm>
451
452
  </FormProvider>;
452
453
  ```
453
454
 
@@ -479,7 +480,7 @@ const typeOptions = [
479
480
  ];
480
481
 
481
482
  <FormProvider {...formMethods}>
482
- <form onSubmit={handleSubmit(onSubmit)}>
483
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
483
484
  <FormSelect<{ type: string }>
484
485
  propertyName='type'
485
486
  label='Type'
@@ -489,7 +490,7 @@ const typeOptions = [
489
490
  requiredText='required'
490
491
  required
491
492
  />
492
- </form>
493
+ </SafeForm>
493
494
  </FormProvider>;
494
495
  ```
495
496
 
@@ -508,9 +509,9 @@ const formMethods = useForm<{ range: string }>({
508
509
  const { handleSubmit } = formMethods;
509
510
 
510
511
  <FormProvider {...formMethods}>
511
- <form onSubmit={handleSubmit(onSubmit)}>
512
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
512
513
  <FormSlider<{ range: string }> propertyName='range' minValue={30} maxValue={90} step={30} />
513
- </form>
514
+ </SafeForm>
514
515
  </FormProvider>;
515
516
  ```
516
517
 
@@ -529,7 +530,7 @@ const formMethods = useForm<{ address: string }>({
529
530
  const { handleSubmit } = formMethods;
530
531
 
531
532
  <FormProvider {...formMethods}>
532
- <form onSubmit={handleSubmit(onSubmit)}>
533
+ <SafeForm onSubmit={handleSubmit(onSubmit)}>
533
534
  <FormText<{ address: string }>
534
535
  maxLength={200}
535
536
  label='address'
@@ -538,7 +539,7 @@ const { handleSubmit } = formMethods;
538
539
  requiredText='required'
539
540
  textarea
540
541
  />
541
- </form>
542
+ </SafeForm>
542
543
  </FormProvider>;
543
544
  ```
544
545
 
@@ -897,21 +898,20 @@ Shows an offline state with icon, title, and optional subtitle. Use `size` 'smal
897
898
  ```jsx
898
899
  import { OfflineView } from '@hortiview/shared-components';
899
900
 
900
- <OfflineView title="Title" subtitle="Subtitle" />
901
+ <OfflineView title='Title' subtitle='Subtitle' />;
901
902
  ```
902
903
 
903
904
  ### OnboardingBanner
904
905
 
905
906
  A responsive onboarding banner that adapts its layout for desktop and mobile.
906
907
 
907
- - **Desktop:** Media content is displayed to the _right_ of the description
908
+ - **Desktop:** Media content is displayed to the _right_ of the description
908
909
  - **Mobile:** Media content appears _above_ the description
909
910
 
910
911
  ```jsx
911
- import {OnboardingBanner} from '@hortiview/shared-components';
912
-
913
- <OnboardingBanner headline='Hello' />
912
+ import { OnboardingBanner } from '@hortiview/shared-components';
914
913
 
914
+ <OnboardingBanner headline='Hello' />;
915
915
  ```
916
916
 
917
917
  ### OverflowTooltip
@@ -930,6 +930,27 @@ const longText =
930
930
  </OverflowTooltip>;
931
931
  ```
932
932
 
933
+ ### SafeForm
934
+
935
+ A wrapper around a form that prevents accidental submission when pressing Enter in input fields.
936
+
937
+ - It handles the 'keydown' event and intercepts the Enter key press.
938
+ - If the focused element is a button, submit button or text area, it allows the default behavior.
939
+ - Otherwise, it prevents the default action to avoid unintended submissions.
940
+
941
+ ```jsx
942
+ import { SafeForm } from '@hortiview/shared-components';
943
+
944
+ <FormProvider {...formMethods}>
945
+ <SafeForm onSubmit={handleSubmit(onSubmitForm)}>
946
+ <Group direction='vertical' primaryAlign='space-between'>
947
+ {children}
948
+ <Button type='submit'>Submit</Button>
949
+ </Group>
950
+ </SafeForm>
951
+ </FormProvider>;
952
+ ```
953
+
933
954
  ### ScrollBar
934
955
 
935
956
  Provides a scrollbar in hortiview styling. Add it a classname on your component.
@@ -1114,11 +1135,17 @@ const overlineTitle = `${getNumberAsLocaleString(userLocale, totalArea, 5)} ${t(
1114
1135
  Formats a date (string) with Intl.DateTimeFormat.
1115
1136
  If locale is a plain code ("en" | "es" | "tr"), it’s mapped to a regional tag ("en-US", "es-MX", "tr-TR").
1116
1137
 
1117
- For consistency, please use the date and time formats defined in `Time.ts`.
1138
+ For consistency, please use `DATE_FORMAT`, `TIME_FORMAT` and `DATE_TIME_FORMAT`.
1118
1139
 
1119
1140
  ```typescript
1120
- getFormattedDateTime('2025-10-02T14:30:00Z', 'en-US', { dateStyle: 'medium' })
1121
- // -> Oct 2, 2025
1141
+ import { DATE_FORMAT, TIME_FORMAT, DATE_TIME_FORMAT } from '@hortiview/shared-components';
1142
+
1143
+ getFormattedDateTime('2025-10-02T14:30:00Z', 'en-US', DATE_FORMAT);
1144
+ // -> 10/02/2025
1145
+ getFormattedDateTime('2025-10-02T14:30:00Z', 'es-MX', TIME_FORMAT);
1146
+ // -> 04:30 p.m.
1147
+ getFormattedDateTime('2025-10-02T14:30:00Z', 'tr-TR', DATE_TIME_FORMAT);
1148
+ // -> 02.10.2025 ÖS 04:30
1122
1149
  ```
1123
1150
 
1124
1151
  ## Available constants
@@ -23,9 +23,9 @@ import '../../assets/DeleteModal.css';const O = "_bulletPoint_bd412_1", j = "_mo
23
23
  icon: g,
24
24
  isIconCrossedOut: h,
25
25
  impossibleDeleteHeader: v,
26
- open: y,
26
+ open: _,
27
27
  setOpen: d,
28
- onDelete: _,
28
+ onDelete: y,
29
29
  onCancel: C,
30
30
  isDeletePossible: m = !0,
31
31
  isOnline: u = !0,
@@ -39,16 +39,16 @@ import '../../assets/DeleteModal.css';const O = "_bulletPoint_bd412_1", j = "_mo
39
39
  offlineViewProps: D,
40
40
  className: `${t.modal}`,
41
41
  modalSize: k ? "small" : "fullscreen",
42
- open: y,
42
+ open: _,
43
43
  title: r,
44
44
  onClose: () => d(!1),
45
- primaryButton: /* @__PURE__ */ o(
45
+ actionButton: /* @__PURE__ */ o(
46
46
  p,
47
47
  {
48
48
  "data-testid": "delete-button",
49
49
  variant: "danger",
50
50
  label: e,
51
- onClick: _,
51
+ onClick: y,
52
52
  disabled: !m || !u
53
53
  }
54
54
  ),
@@ -27,7 +27,7 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
27
27
  }, ut = ({
28
28
  clearFilterText: m,
29
29
  closeCallback: s,
30
- currentFilter: i,
30
+ currentFilter: r,
31
31
  filterButtonAsIcon: d = !1,
32
32
  filterButtonText: a,
33
33
  filterModalTitle: t,
@@ -35,21 +35,21 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
35
35
  modalCancelButtonText: g,
36
36
  modalConfirmButtonText: p,
37
37
  useModal: o = !0,
38
- selectAllLabel: r,
38
+ selectAllLabel: i,
39
39
  "data-testid": w
40
40
  }) => {
41
- const { isDesktop: A } = k(), [$, B] = v(!1), [c, y] = v(i), [q, C] = v(0), x = () => {
42
- B(!1), s(c), C(
41
+ const { isDesktop: A } = k(), [$, B] = v(!1), [c, C] = v(r), [q, x] = v(0), y = () => {
42
+ B(!1), s(c), x(
43
43
  c.reduce((l, { filterValue: n }) => n === void 0 ? l : typeof n == "boolean" ? n ? l + 1 : l : Array.isArray(n) ? l + n.length : typeof n == "string" && n.length ? l + 1 : l, 0)
44
44
  );
45
45
  }, O = () => {
46
- y([]), C(0);
46
+ C([]), x(0);
47
47
  }, S = (l) => {
48
48
  const n = [
49
49
  ...c.filter((P) => P.id !== l.id),
50
50
  l
51
51
  ];
52
- y(n), o || s(n);
52
+ C(n), o || s(n);
53
53
  };
54
54
  return o ? /* @__PURE__ */ b(D, { children: [
55
55
  /* @__PURE__ */ e(
@@ -66,7 +66,7 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
66
66
  H,
67
67
  {
68
68
  open: $,
69
- onClose: x,
69
+ onClose: y,
70
70
  title: t,
71
71
  modalSize: A ? "small" : "fullscreen",
72
72
  headerActions: /* @__PURE__ */ e(h, { "data-testid": "filter-clear-button", variant: "text", onClick: O, children: m }),
@@ -79,12 +79,12 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
79
79
  children: g
80
80
  }
81
81
  ),
82
- primaryButton: /* @__PURE__ */ e(h, { "data-testid": "filter-confirm-button", variant: "filled", onClick: x, children: p }),
83
- children: /* @__PURE__ */ e(_, { direction: "vertical", "data-testid": "filter-map-filters", children: N(f, c, S, r) })
82
+ actionButton: /* @__PURE__ */ e(h, { "data-testid": "filter-confirm-button", variant: "filled", onClick: y, children: p }),
83
+ children: /* @__PURE__ */ e(_, { direction: "vertical", "data-testid": "filter-map-filters", children: N(f, c, S, i) })
84
84
  }
85
85
  )
86
- ] }) : /* @__PURE__ */ e(_, { secondaryAlign: "center", fullWidth: !0, children: N(f, c, S, r, !1) });
87
- }, N = (m, s, i, d, a = !0) => m.map(({ id: t, title: f, availableOptions: g, icon: p, type: o }) => /* @__PURE__ */ b(_, { fullWidth: !0, secondaryAlign: "center", "data-testid": `filter-${o}-group-${t}`, children: [
86
+ ] }) : /* @__PURE__ */ e(_, { secondaryAlign: "center", fullWidth: !0, children: N(f, c, S, i, !1) });
87
+ }, N = (m, s, r, d, a = !0) => m.map(({ id: t, title: f, availableOptions: g, icon: p, type: o }) => /* @__PURE__ */ b(_, { fullWidth: !0, secondaryAlign: "center", "data-testid": `filter-${o}-group-${t}`, children: [
88
88
  p ? /* @__PURE__ */ e(z, { icon: p, iconSize: "medium" }) : null,
89
89
  o === "select" && /* @__PURE__ */ e(
90
90
  I,
@@ -98,8 +98,8 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
98
98
  multiSelect: !0,
99
99
  textKey: "text",
100
100
  valueKey: "id",
101
- value: s.find((r) => r.id === t)?.filterValue ?? [],
102
- onChange: (r) => i({ id: t, type: o, filterValue: r }),
101
+ value: s.find((i) => i.id === t)?.filterValue ?? [],
102
+ onChange: (i) => r({ id: t, type: o, filterValue: i }),
103
103
  hoisted: !0,
104
104
  menuMaxHeight: "300px",
105
105
  disabled: t === "location",
@@ -114,8 +114,8 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
114
114
  {
115
115
  "data-testid": `filter-switch-${t}`,
116
116
  label: f,
117
- onChange: (r) => i({ id: t, type: o, filterValue: r }),
118
- checked: !!s.find((r) => r.id === t)?.filterValue
117
+ onChange: (i) => r({ id: t, type: o, filterValue: i }),
118
+ checked: !!s.find((i) => i.id === t)?.filterValue
119
119
  }
120
120
  ),
121
121
  o === "search" && /* @__PURE__ */ e(
@@ -123,14 +123,14 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
123
123
  {
124
124
  "data-testid": `filter-search-${t}`,
125
125
  placeholder: f,
126
- searchTerm: s.find((r) => r.id === t)?.filterValue,
127
- setSearchTerm: (r) => i({ id: t, type: o, filterValue: r })
126
+ searchTerm: s.find((i) => i.id === t)?.filterValue,
127
+ setSearchTerm: (i) => r({ id: t, type: o, filterValue: i })
128
128
  }
129
129
  )
130
130
  ] }, t)), J = ({
131
131
  filterButtonText: m,
132
132
  filterButtonAsIcon: s,
133
- count: i,
133
+ count: r,
134
134
  "data-testid": d,
135
135
  onClick: a
136
136
  }) => {
@@ -141,10 +141,10 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
141
141
  "data-testid": d ?? "filter-icon-button",
142
142
  icon: "filter_list_alt",
143
143
  onClick: a,
144
- badge: i !== 0 && /* @__PURE__ */ e(
144
+ badge: r !== 0 && /* @__PURE__ */ e(
145
145
  F,
146
146
  {
147
- counter: i,
147
+ counter: r,
148
148
  className: u.filterBadge,
149
149
  themeColor: "secondary",
150
150
  "data-testid": "filter-badge"
@@ -171,10 +171,10 @@ import '../../assets/Filter.css';const K = "_filterButton_qtl7a_1", T = "_relati
171
171
  children: m
172
172
  }
173
173
  ),
174
- i !== 0 && /* @__PURE__ */ e(
174
+ r !== 0 && /* @__PURE__ */ e(
175
175
  F,
176
176
  {
177
- counter: i,
177
+ counter: r,
178
178
  className: u.filterBadge,
179
179
  themeColor: "secondary",
180
180
  "data-testid": "filter-badge"
@@ -2,7 +2,7 @@ import { ModalProps as ElementModalProps } from '@element-public/react-modal';
2
2
  import { AvailableCustomIcons } from '../../enums/AvailableCustomIcons';
3
3
  import { OfflineViewProps } from '../OfflineView/OfflineView';
4
4
 
5
- type ModalProps = ElementModalProps & React.HTMLProps<HTMLElement> & React.DOMAttributes<HTMLElement> & {
5
+ type ModalProps = Omit<ElementModalProps, 'primaryButton'> & React.HTMLProps<HTMLElement> & React.DOMAttributes<HTMLElement> & {
6
6
  leadingIcon?: keyof typeof AvailableCustomIcons | string;
7
7
  isOnline?: boolean;
8
8
  offlineViewProps?: Partial<OfflineViewProps>;
@@ -13,12 +13,13 @@ type ModalProps = ElementModalProps & React.HTMLProps<HTMLElement> & React.DOMAt
13
13
  * @param onClose - The function to call when the modal is closed - Should be passed to the modal.
14
14
  * @param title - The title of the modal.
15
15
  * @param headerActions - The actions to display in the header of the modal.
16
- * @param hideCloseIcon - If true, the close icon will be hidden. @default true.
16
+ * @param actionButton - Button for the primary action of the modal - primaryButton is omitted from {@link ModalProps} since it triggers form submission on Enter key press.
17
+ * @param hideCloseIcon - If true, the close icon will be hidden. Default true.
17
18
  * @param leadingIcon - Iconify icon string (material icons and custom icons)
18
- * @param - Other element props to pass to the modal.
19
19
  * @param isOnline - Whether the user is online; shows OfflineView when false.
20
20
  * @param offlineViewProps - Props forwarded to OfflineView when offline.
21
+ * @param ...props - Other element props to pass to the modal.
21
22
  * @returns
22
23
  */
23
- export declare const Modal: ({ onClose, title, headerActions, hideCloseIcon, leadingIcon, isOnline, offlineViewProps, children, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
24
+ export declare const Modal: ({ onClose, title, headerActions, actionButton, hideCloseIcon, leadingIcon, isOnline, offlineViewProps, children, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
24
25
  export {};
@@ -1,8 +1,8 @@
1
1
  import { jsxs as ft, jsx as C, Fragment as pt } from "react/jsx-runtime";
2
- import { G as z } from "../../index.es-CbBdaRO2.js";
2
+ import { G as j } from "../../index.es-CbBdaRO2.js";
3
3
  import { I as it } from "../../index.es-Kg9soDed.js";
4
4
  import { _ as ht, c as B, P as s } from "../../_setToString-Do1lSQTZ.js";
5
- import d, { forwardRef as gt, useRef as et, useImperativeHandle as _t, useState as nt, useEffect as E, useCallback as j, useMemo as Y, Fragment as Et } from "react";
5
+ import d, { forwardRef as gt, useRef as et, useImperativeHandle as _t, useState as nt, useEffect as E, useCallback as q, useMemo as J, Fragment as Et } from "react";
6
6
  import { i as Ct, c as b, a as St } from "../../index.es-DlzwTKbh.js";
7
7
  import { b as at, c as ot, d as vt } from "../../tslib.es6-BDCynO9F.js";
8
8
  import { M as yt, a as Ot } from "../../component-neHBNHRu.js";
@@ -74,7 +74,7 @@ function kt(i) {
74
74
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75
75
  * THE SOFTWARE.
76
76
  */
77
- var q = "mdc-dom-focus-sentinel", Ht = (
77
+ var $ = "mdc-dom-focus-sentinel", Ht = (
78
78
  /** @class */
79
79
  function() {
80
80
  function i(e, t) {
@@ -86,7 +86,7 @@ var q = "mdc-dom-focus-sentinel", Ht = (
86
86
  throw new Error("FocusTrap: Element must have at least one focusable child.");
87
87
  this.elFocusedBeforeTrapFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null, this.wrapTabFocus(this.root), this.options.skipInitialFocus || this.focusInitialElement(e, this.options.initialFocusEl);
88
88
  }, i.prototype.releaseFocus = function() {
89
- [].slice.call(this.root.querySelectorAll("." + q)).forEach(function(e) {
89
+ [].slice.call(this.root.querySelectorAll("." + $)).forEach(function(e) {
90
90
  e.parentElement.removeChild(e);
91
91
  }), !this.options.skipRestoreFocus && this.elFocusedBeforeTrapFocus && this.elFocusedBeforeTrapFocus.focus();
92
92
  }, i.prototype.wrapTabFocus = function(e) {
@@ -104,16 +104,16 @@ var q = "mdc-dom-focus-sentinel", Ht = (
104
104
  }, i.prototype.getFocusableElements = function(e) {
105
105
  var t = [].slice.call(e.querySelectorAll("[autofocus], [tabindex], a, input, textarea, select, button"));
106
106
  return t.filter(function(n) {
107
- var o = n.getAttribute("aria-disabled") === "true" || n.getAttribute("disabled") != null || n.getAttribute("hidden") != null || n.getAttribute("aria-hidden") === "true", a = n.tabIndex >= 0 && n.getBoundingClientRect().width > 0 && !n.classList.contains(q) && !o, f = !1;
107
+ var o = n.getAttribute("aria-disabled") === "true" || n.getAttribute("disabled") != null || n.getAttribute("hidden") != null || n.getAttribute("aria-hidden") === "true", a = n.tabIndex >= 0 && n.getBoundingClientRect().width > 0 && !n.classList.contains($) && !o, f = !1;
108
108
  if (a) {
109
- var h = getComputedStyle(n);
110
- f = h.display === "none" || h.visibility === "hidden";
109
+ var p = getComputedStyle(n);
110
+ f = p.display === "none" || p.visibility === "hidden";
111
111
  }
112
112
  return a && !f;
113
113
  });
114
114
  }, i.prototype.createSentinel = function() {
115
115
  var e = document.createElement("div");
116
- return e.setAttribute("tabindex", "0"), e.setAttribute("aria-hidden", "true"), e.classList.add(q), e;
116
+ return e.setAttribute("tabindex", "0"), e.setAttribute("aria-hidden", "true"), e.classList.add($), e;
117
117
  }, i;
118
118
  }()
119
119
  );
@@ -172,7 +172,7 @@ var r = {
172
172
  // to prevent interactions with the content behind this scrim, and to capture
173
173
  // scrim clicks.
174
174
  SCRIM_HIDDEN: "mdc-dialog__scrim--hidden"
175
- }, v = {
175
+ }, y = {
176
176
  ACTION_ATTRIBUTE: "data-mdc-dialog-action",
177
177
  BUTTON_DEFAULT_ATTRIBUTE: "data-mdc-dialog-button-default",
178
178
  BUTTON_SELECTOR: ".mdc-dialog__button",
@@ -192,7 +192,7 @@ var r = {
192
192
  ".mdc-menu .mdc-deprecated-list-item"
193
193
  ].join(", "),
194
194
  SURFACE_SELECTOR: ".mdc-dialog__surface"
195
- }, $ = {
195
+ }, Y = {
196
196
  DIALOG_ANIMATION_CLOSE_TIME_MS: 75,
197
197
  DIALOG_ANIMATION_OPEN_TIME_MS: 150
198
198
  };
@@ -228,7 +228,7 @@ var rt = (
228
228
  at(e, i);
229
229
  function e(t) {
230
230
  var n = i.call(this, ot(ot({}, e.defaultAdapter), t)) || this;
231
- return n.dialogOpen = !1, n.isFullscreen = !1, n.animationFrame = 0, n.animationTimer = 0, n.escapeKeyAction = v.CLOSE_ACTION, n.scrimClickAction = v.CLOSE_ACTION, n.autoStackButtons = !0, n.areButtonsStacked = !1, n.suppressDefaultPressSelector = v.SUPPRESS_DEFAULT_PRESS_SELECTOR, n.animFrame = new Dt(), n.contentScrollHandler = function() {
231
+ return n.dialogOpen = !1, n.isFullscreen = !1, n.animationFrame = 0, n.animationTimer = 0, n.escapeKeyAction = y.CLOSE_ACTION, n.scrimClickAction = y.CLOSE_ACTION, n.autoStackButtons = !0, n.areButtonsStacked = !1, n.suppressDefaultPressSelector = y.SUPPRESS_DEFAULT_PRESS_SELECTOR, n.animFrame = new Dt(), n.contentScrollHandler = function() {
232
232
  n.handleScrollEvent();
233
233
  }, n.windowResizeHandler = function() {
234
234
  n.layout();
@@ -244,13 +244,13 @@ var rt = (
244
244
  configurable: !0
245
245
  }), Object.defineProperty(e, "strings", {
246
246
  get: function() {
247
- return v;
247
+ return y;
248
248
  },
249
249
  enumerable: !1,
250
250
  configurable: !0
251
251
  }), Object.defineProperty(e, "numbers", {
252
252
  get: function() {
253
- return $;
253
+ return Y;
254
254
  },
255
255
  enumerable: !1,
256
256
  configurable: !0
@@ -320,19 +320,19 @@ var rt = (
320
320
  }), e.prototype.init = function() {
321
321
  this.adapter.hasClass(r.STACKED) && this.setAutoStackButtons(!1), this.isFullscreen = this.adapter.hasClass(r.FULLSCREEN);
322
322
  }, e.prototype.destroy = function() {
323
- this.dialogOpen && this.close(v.DESTROY_ACTION), this.animationTimer && (clearTimeout(this.animationTimer), this.handleAnimationTimerEnd()), this.isFullscreen && this.adapter.deregisterContentEventHandler("scroll", this.contentScrollHandler), this.animFrame.cancelAll(), this.adapter.deregisterWindowEventHandler("resize", this.windowResizeHandler), this.adapter.deregisterWindowEventHandler("orientationchange", this.windowOrientationChangeHandler);
323
+ this.dialogOpen && this.close(y.DESTROY_ACTION), this.animationTimer && (clearTimeout(this.animationTimer), this.handleAnimationTimerEnd()), this.isFullscreen && this.adapter.deregisterContentEventHandler("scroll", this.contentScrollHandler), this.animFrame.cancelAll(), this.adapter.deregisterWindowEventHandler("resize", this.windowResizeHandler), this.adapter.deregisterWindowEventHandler("orientationchange", this.windowOrientationChangeHandler);
324
324
  }, e.prototype.open = function(t) {
325
325
  var n = this;
326
326
  this.dialogOpen = !0, this.adapter.notifyOpening(), this.adapter.addClass(r.OPENING), this.isFullscreen && this.adapter.registerContentEventHandler("scroll", this.contentScrollHandler), t && t.isAboveFullscreenDialog && this.adapter.addClass(r.SCRIM_HIDDEN), this.adapter.registerWindowEventHandler("resize", this.windowResizeHandler), this.adapter.registerWindowEventHandler("orientationchange", this.windowOrientationChangeHandler), this.runNextAnimationFrame(function() {
327
327
  n.adapter.addClass(r.OPEN), n.adapter.addBodyClass(r.SCROLL_LOCK), n.layout(), n.animationTimer = setTimeout(function() {
328
328
  n.handleAnimationTimerEnd(), n.adapter.trapFocus(n.adapter.getInitialFocusEl()), n.adapter.notifyOpened();
329
- }, $.DIALOG_ANIMATION_OPEN_TIME_MS);
329
+ }, Y.DIALOG_ANIMATION_OPEN_TIME_MS);
330
330
  });
331
331
  }, e.prototype.close = function(t) {
332
332
  var n = this;
333
333
  t === void 0 && (t = ""), this.dialogOpen && (this.dialogOpen = !1, this.adapter.notifyClosing(t), this.adapter.addClass(r.CLOSING), this.adapter.removeClass(r.OPEN), this.adapter.removeBodyClass(r.SCROLL_LOCK), this.isFullscreen && this.adapter.deregisterContentEventHandler("scroll", this.contentScrollHandler), this.adapter.deregisterWindowEventHandler("resize", this.windowResizeHandler), this.adapter.deregisterWindowEventHandler("orientationchange", this.windowOrientationChangeHandler), cancelAnimationFrame(this.animationFrame), this.animationFrame = 0, clearTimeout(this.animationTimer), this.animationTimer = setTimeout(function() {
334
334
  n.adapter.releaseFocus(), n.handleAnimationTimerEnd(), n.adapter.notifyClosed(t);
335
- }, $.DIALOG_ANIMATION_CLOSE_TIME_MS));
335
+ }, Y.DIALOG_ANIMATION_CLOSE_TIME_MS));
336
336
  }, e.prototype.showSurfaceScrim = function() {
337
337
  var t = this;
338
338
  this.adapter.addClass(r.SURFACE_SCRIM_SHOWING), this.runNextAnimationFrame(function() {
@@ -366,7 +366,7 @@ var rt = (
366
366
  t.layoutInternal();
367
367
  });
368
368
  }, e.prototype.handleClick = function(t) {
369
- var n = this.adapter.eventTargetMatches(t.target, v.SCRIM_SELECTOR);
369
+ var n = this.adapter.eventTargetMatches(t.target, y.SCRIM_SELECTOR);
370
370
  if (n && this.scrimClickAction !== "")
371
371
  this.close(this.scrimClickAction);
372
372
  else {
@@ -478,23 +478,23 @@ var u = rt.strings, Pt = (
478
478
  return new e(t);
479
479
  }, e.prototype.initialize = function(t) {
480
480
  var n, o;
481
- t === void 0 && (t = function(g, p) {
482
- return new Ht(g, p);
481
+ t === void 0 && (t = function(h, S) {
482
+ return new Ht(h, S);
483
483
  });
484
484
  var a = this.root.querySelector(u.CONTAINER_SELECTOR);
485
485
  if (!a)
486
486
  throw new Error("Dialog component requires a " + u.CONTAINER_SELECTOR + " container element");
487
487
  this.container = a, this.content = this.root.querySelector(u.CONTENT_SELECTOR), this.buttons = [].slice.call(this.root.querySelectorAll(u.BUTTON_SELECTOR)), this.defaultButton = this.root.querySelector("[" + u.BUTTON_DEFAULT_ATTRIBUTE + "]"), this.focusTrapFactory = t, this.buttonRipples = [];
488
488
  try {
489
- for (var f = vt(this.buttons), h = f.next(); !h.done; h = f.next()) {
490
- var S = h.value;
491
- this.buttonRipples.push(new Tt(S));
489
+ for (var f = vt(this.buttons), p = f.next(); !p.done; p = f.next()) {
490
+ var v = p.value;
491
+ this.buttonRipples.push(new Tt(v));
492
492
  }
493
- } catch (g) {
494
- n = { error: g };
493
+ } catch (h) {
494
+ n = { error: h };
495
495
  } finally {
496
496
  try {
497
- h && !h.done && (o = f.return) && o.call(f);
497
+ p && !p.done && (o = f.return) && o.call(f);
498
498
  } finally {
499
499
  if (n) throw n.error;
500
500
  }
@@ -796,38 +796,38 @@ const Ut = {
796
796
  badge: o,
797
797
  backButton: a,
798
798
  children: f,
799
- className: h,
800
- content: S,
801
- defaultButton: g,
802
- dismissiveButton: p,
803
- footerSupplemental: y,
804
- headerActions: J,
805
- hideCloseIcon: H,
799
+ className: p,
800
+ content: v,
801
+ defaultButton: h,
802
+ dismissiveButton: S,
803
+ footerSupplemental: g,
804
+ headerActions: H,
805
+ hideCloseIcon: P,
806
806
  indicator: st,
807
807
  initialFocus: O,
808
- mobileStackedButtons: P,
808
+ mobileStackedButtons: U,
809
809
  modalSize: _,
810
810
  nextButton: T,
811
811
  noActions: A,
812
- onClose: U,
813
- onClosed: x,
812
+ onClose: x,
813
+ onClosed: G,
814
814
  onOpen: D,
815
815
  onOpened: I,
816
816
  open: Q,
817
- preventClose: G,
817
+ preventClose: K,
818
818
  preventPrimaryAccept: X,
819
819
  primaryButton: c,
820
- returnFocusSelector: K,
820
+ returnFocusSelector: W,
821
821
  scrollable: Z,
822
822
  title: tt,
823
823
  ...lt
824
824
  } = i, N = et(), l = et();
825
825
  _t(e, () => N.current, []);
826
- const [W, ct] = nt(), [V, dt] = nt(() => T || a);
826
+ const [V, ct] = nt(), [z, dt] = nt(() => T || a);
827
827
  E(() => {
828
828
  dt(T || a);
829
829
  }, [T, a]);
830
- const L = j(() => {
830
+ const L = q(() => {
831
831
  ct(window.innerWidth <= 600);
832
832
  }, []);
833
833
  E(() => (L(), window.addEventListener("resize", L), () => {
@@ -835,18 +835,18 @@ const Ut = {
835
835
  }), [L]), E(() => (l.current = Pt.attachTo(N.current), () => {
836
836
  l.current.destroy();
837
837
  }), [l, N]), E(() => {
838
- l.current.foundation.setAutoStackButtons(P);
839
- }, [P]), E(() => {
838
+ l.current.foundation.setAutoStackButtons(U);
839
+ }, [U]), E(() => {
840
840
  A && (l.current.foundation.adapter.trapFocus = () => {
841
841
  });
842
842
  }, [A]), E(() => {
843
- l.current.scrimClickAction = G ? "" : "close", l.current.escapeKeyAction = G ? "" : "close";
844
- }, [G]);
845
- const F = j((m) => {
846
- U && U(m);
847
- }, [U]), R = j((m) => {
848
- K && Ct(K), x && x(m);
849
- }, [K, x]);
843
+ l.current.scrimClickAction = K ? "" : "close", l.current.escapeKeyAction = K ? "" : "close";
844
+ }, [K]);
845
+ const F = q((m) => {
846
+ x && x(m);
847
+ }, [x]), R = q((m) => {
848
+ W && Ct(W), G && G(m);
849
+ }, [W, G]);
850
850
  E(() => (l.current.unlisten("MDCDialog: opening", D), l.current.listen("MDCDialog: opening", D), () => {
851
851
  l.current.unlisten("MDCDialog: opening", D);
852
852
  }), [l, D]), E(() => (l.current.unlisten("MDCDialog:opened", I), l.current.listen("MDCDialog:opened", I), () => {
@@ -858,59 +858,59 @@ const Ut = {
858
858
  }), [l, R]), E(() => {
859
859
  Q ? l.current.open() : l.current.close();
860
860
  }, [l, Q]);
861
- const ut = Y(() => () => {
861
+ const ut = J(() => () => {
862
862
  const m = {
863
863
  className: "lmnt-modal__button mdc-dialog__button",
864
864
  elevation: t?.props.elevation !== "default" ? t?.props.elevation : "flat",
865
865
  variant: t?.props.variant || "filled"
866
866
  };
867
- return g === "action" && (m["data-mdc-dialog-button-default"] = !0), O === "action" && (m["data-mdc-dialog-initial-focus"] = !0), m;
868
- }, [t?.props.elevation, t?.props.variant, g, O]), mt = Y(() => () => {
867
+ return h === "action" && (m["data-mdc-dialog-button-default"] = !0), O === "action" && (m["data-mdc-dialog-initial-focus"] = !0), m;
868
+ }, [t?.props.elevation, t?.props.variant, h, O]), mt = J(() => () => {
869
869
  const m = {
870
870
  className: "lmnt-modal__button mdc-dialog__button",
871
871
  "data-mdc-dialog-action": X ? "" : "accept",
872
872
  elevation: c?.props.elevation !== "default" ? c?.props.elevation : "flat",
873
873
  variant: c?.props.variant || "filled"
874
874
  };
875
- return g === "primary" && (m["data-mdc-dialog-button-default"] = !0), O === "primary" && (m["data-mdc-dialog-initial-focus"] = !0), m;
876
- }, [X, g, O, c?.props.elevation, c?.props.variant]);
875
+ return h === "primary" && (m["data-mdc-dialog-button-default"] = !0), O === "primary" && (m["data-mdc-dialog-initial-focus"] = !0), m;
876
+ }, [X, h, O, c?.props.elevation, c?.props.variant]);
877
877
  return /* @__PURE__ */ d.createElement("aside", ht({
878
878
  ref: N,
879
- className: B("lmnt", "lmnt-modal", "mdc-dialog", Z && "lmnt-modal--scrollable mdc-dialog--scrollable", h),
879
+ className: B("lmnt", "lmnt-modal", "mdc-dialog", Z && "lmnt-modal--scrollable mdc-dialog--scrollable", p),
880
880
  role: "alertdialog"
881
881
  }, lt), /* @__PURE__ */ d.createElement("div", {
882
- className: B("lmnt-modal__container", "mdc-dialog__container", _ === "fullscreen" && "mdc-dialog--fullscreen", _ === "max" && "lmnt-modal__max", _ === "xlarge" && "lmnt-modal__xl", _ === "large" && "lmnt-modal__lg", _ === "medium" && "lmnt-modal__md", _ === "small" && "lmnt-modal__sm", (_ === "mobile" || W) && "lmnt-modal__mobile", _ === "dialog" && "lmnt-modal__dialog", A && "lmnt-modal-no-actions")
882
+ className: B("lmnt-modal__container", "mdc-dialog__container", _ === "fullscreen" && "mdc-dialog--fullscreen", _ === "max" && "lmnt-modal__max", _ === "xlarge" && "lmnt-modal__xl", _ === "large" && "lmnt-modal__lg", _ === "medium" && "lmnt-modal__md", _ === "small" && "lmnt-modal__sm", (_ === "mobile" || V) && "lmnt-modal__mobile", _ === "dialog" && "lmnt-modal__dialog", A && "lmnt-modal-no-actions")
883
883
  }, /* @__PURE__ */ d.createElement("div", {
884
884
  className: "lmnt-modal__surface mdc-dialog__surface"
885
885
  }, /* @__PURE__ */ d.createElement("header", {
886
- className: B("lmnt-modal__title", "mdc-dialog__title", (_ === "dialog" || H) && "lmnt-modal_title-hide-close-icon", n && "lmnt-modal_title-actionsIcons", Z && "lmnt-modal__title-scrollable", (H || _ === "dialog" || A) && "lmnt-modal--no-close-icon")
887
- }, !H && _ !== "dialog" && !A && /* @__PURE__ */ d.createElement(it, {
886
+ className: B("lmnt-modal__title", "mdc-dialog__title", (_ === "dialog" || P) && "lmnt-modal_title-hide-close-icon", n && "lmnt-modal_title-actionsIcons", Z && "lmnt-modal__title-scrollable", (P || _ === "dialog" || A) && "lmnt-modal--no-close-icon")
887
+ }, !P && _ !== "dialog" && !A && /* @__PURE__ */ d.createElement(it, {
888
888
  className: "mdc-icon-button material-icons mdc-dialog__close",
889
889
  "data-mdc-dialog-action": "close",
890
890
  icon: "clear"
891
- }), tt && /* @__PURE__ */ d.createElement("div", null, tt), J && /* @__PURE__ */ d.createElement("div", {
891
+ }), tt && /* @__PURE__ */ d.createElement("div", null, tt), H && /* @__PURE__ */ d.createElement("div", {
892
892
  className: "lmnt-dialog__title-actions"
893
- }, J), o && /* @__PURE__ */ d.createElement("div", {
893
+ }, H), o && /* @__PURE__ */ d.createElement("div", {
894
894
  className: "lmnt-badge--modal",
895
895
  style: {
896
896
  marginLeft: "0"
897
897
  }
898
- }, o)), (S || f) && /* @__PURE__ */ d.createElement("section", {
898
+ }, o)), (v || f) && /* @__PURE__ */ d.createElement("section", {
899
899
  className: "lmnt-modal__content mdc-dialog__content"
900
- }, S || f), st, (t || a || p || T || c || y) && /* @__PURE__ */ d.createElement("footer", {
901
- className: B("lmnt-modal__actions", "mdc-dialog__actions", W && "lmnt-dialog__actions__mobile", y && "lmnt-modal__actions--supplemental-btn", W && P && "lmnt-modal_actions-mobile-stacked")
902
- }, !V && y && /* @__PURE__ */ d.createElement("div", {
900
+ }, v || f), st, (t || a || S || T || c || g) && /* @__PURE__ */ d.createElement("footer", {
901
+ className: B("lmnt-modal__actions", "mdc-dialog__actions", V && "lmnt-dialog__actions__mobile", g && "lmnt-modal__actions--supplemental-btn", V && U && "lmnt-modal_actions-mobile-stacked")
902
+ }, !z && g && /* @__PURE__ */ d.createElement("div", {
903
903
  className: "lmnt-dialog__actions__supplemental"
904
- }, b(y, () => {
904
+ }, b(g, () => {
905
905
  const m = {};
906
- return g === "footerSupplemental" && (m["data-mdc-dialog-button-default"] = !0), O === "footerSupplemental" && (m["data-mdc-dialog-initial-focus"] = !0), m;
907
- })), !V && (t || p || c) && /* @__PURE__ */ d.createElement("div", {
906
+ return h === "footerSupplemental" && (m["data-mdc-dialog-button-default"] = !0), O === "footerSupplemental" && (m["data-mdc-dialog-initial-focus"] = !0), m;
907
+ })), !z && (t || S || c) && /* @__PURE__ */ d.createElement("div", {
908
908
  className: "lmnt-dialog__actions__right-align lmnt-modal_actions_button"
909
- }, p && b(p, {
909
+ }, S && b(S, {
910
910
  variant: "text",
911
911
  className: "lmnt-modal__button mdc-dialog__button",
912
912
  "data-mdc-dialog-action": "close"
913
- }), t && !c && b(t, ut), c && b(c, mt)), V && /* @__PURE__ */ d.createElement("div", {
913
+ }), t && !c && b(t, ut), c && b(c, mt)), z && /* @__PURE__ */ d.createElement("div", {
914
914
  className: "lmnt-modal_actions_button lmnt-dialog__actions__directional"
915
915
  }, /* @__PURE__ */ d.createElement("div", null, St(a, "lmnt-modal__button")), /* @__PURE__ */ d.createElement("div", null, b(T, {
916
916
  className: "lmnt-modal__button",
@@ -931,18 +931,19 @@ const Gt = "_modal_fr8bw_1", Kt = "_title_fr8bw_6", Wt = "_titleWithoutCloseIcon
931
931
  onClose: i,
932
932
  title: e,
933
933
  headerActions: t,
934
- hideCloseIcon: n,
935
- leadingIcon: o,
936
- isOnline: a = !0,
937
- offlineViewProps: f,
938
- children: h,
939
- ...S
934
+ actionButton: n,
935
+ hideCloseIcon: o,
936
+ leadingIcon: a,
937
+ isOnline: f = !0,
938
+ offlineViewProps: p,
939
+ children: v,
940
+ ...h
940
941
  }) => {
941
- const g = Y(() => {
942
- const p = {
942
+ const S = J(() => {
943
+ const g = {
943
944
  id: "base",
944
- action: /* @__PURE__ */ ft(z, { primaryAlign: "center", secondaryAlign: "center", children: [
945
- !n && /* @__PURE__ */ C(
945
+ action: /* @__PURE__ */ ft(j, { primaryAlign: "center", secondaryAlign: "center", children: [
946
+ !o && /* @__PURE__ */ C(
946
947
  it,
947
948
  {
948
949
  icon: "close",
@@ -951,29 +952,30 @@ const Gt = "_modal_fr8bw_1", Kt = "_title_fr8bw_6", Wt = "_titleWithoutCloseIcon
951
952
  className: w.closeButton
952
953
  }
953
954
  ),
954
- o ? /* @__PURE__ */ C(It, { customPadding: "0.25rem 0 0 0.75rem", children: /* @__PURE__ */ C(Lt, { icon: o }) }) : /* @__PURE__ */ C(pt, {}),
955
+ a ? /* @__PURE__ */ C(It, { customPadding: "0.25rem 0 0 0.75rem", children: /* @__PURE__ */ C(Lt, { icon: a }) }) : /* @__PURE__ */ C(pt, {}),
955
956
  /* @__PURE__ */ C(
956
957
  Nt,
957
958
  {
958
959
  level: 6,
959
- className: n && !o ? w.titleWithoutCloseIcon : "",
960
+ className: o && !a ? w.titleWithoutCloseIcon : "",
960
961
  children: e
961
962
  }
962
963
  )
963
964
  ] }, "base-group")
964
965
  };
965
- return t ? Array.isArray(t) ? [p, { id: "action-group", action: /* @__PURE__ */ C(z, { children: t }, "action-group") }] : [p, { id: "action", action: t }] : [p];
966
- }, [t, n, o, i, e]);
966
+ return t ? Array.isArray(t) ? [g, { id: "action-group", action: /* @__PURE__ */ C(j, { children: t }, "action-group") }] : [g, { id: "action", action: t }] : [g];
967
+ }, [t, o, a, i, e]);
967
968
  return /* @__PURE__ */ C(
968
969
  k,
969
970
  {
970
- ...S,
971
+ ...h,
971
972
  "data-testid": "modal",
972
- className: `${w.modal} ${w.title} ${S.className ?? ""}`,
973
+ className: `${w.modal} ${w.title} ${h.className ?? ""}`,
973
974
  hideCloseIcon: !0,
974
- headerActions: /* @__PURE__ */ C(z, { primaryAlign: "space-between", secondaryAlign: "center", children: g.map((p) => /* @__PURE__ */ C(Et, { children: p.action }, p.id)) }, "header-group"),
975
+ actionButton: n,
976
+ headerActions: /* @__PURE__ */ C(j, { primaryAlign: "space-between", secondaryAlign: "center", children: S.map((g) => /* @__PURE__ */ C(Et, { children: g.action }, g.id)) }, "header-group"),
975
977
  preventClose: !0,
976
- children: a ? h : /* @__PURE__ */ C(Ft, { ...f })
978
+ children: f ? v : /* @__PURE__ */ C(Ft, { ...p })
977
979
  }
978
980
  );
979
981
  };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A form component that prevents accidental submission when pressing Enter in input fields.
3
+ * It handles the 'keydown' event and intercepts the Enter key press.
4
+ * If the focused element is a button, submit button or text area, it allows the default behavior.
5
+ * Otherwise, it prevents the default action to avoid unintended submissions.
6
+ *
7
+ * @param children - The form children elements.
8
+ * @param props - Additional form props.
9
+ * @returns JSX.Element
10
+ */
11
+ export declare const SafeForm: ({ children, ...props }: JSX.IntrinsicElements["form"]) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ const a = ({ children: t, ...r }) => /* @__PURE__ */ e("form", { onKeyDown: n, ...r, children: t }), n = async (t) => {
3
+ if (t.key !== "Enter") return;
4
+ const r = t.target;
5
+ r?.type !== "submit" && r?.type !== "button" && r?.type !== "textarea" && (t.preventDefault(), t.stopPropagation());
6
+ };
7
+ export {
8
+ a as SafeForm
9
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,91 @@
1
+ import { jsxs as a, jsx as t } from "react/jsx-runtime";
2
+ import { a as u, s as i, f as r } from "../../react.esm-CX1WJ2Pp.js";
3
+ import { u as y } from "../../index-I7uTh4Tr.js";
4
+ import { SafeForm as p } from "./SafeForm.js";
5
+ import { d as b, t as c, g as s, v as l } from "../../vi.CjhMlMwf-CKxPQtd6.js";
6
+ b("SafeForm", () => {
7
+ c("renders form with children", () => {
8
+ u(
9
+ /* @__PURE__ */ a(p, { children: [
10
+ /* @__PURE__ */ t("input", { "data-testid": "test-input", type: "text" }),
11
+ /* @__PURE__ */ t("button", { "data-testid": "submit-button", type: "submit", children: "Submit" })
12
+ ] })
13
+ ), s(i.getByTestId("test-input")).toBeInTheDocument(), s(i.getByTestId("submit-button")).toBeInTheDocument();
14
+ }), c("prevents Enter key default behavior on text inputs", async () => {
15
+ const e = y.setup();
16
+ u(
17
+ /* @__PURE__ */ a(p, { children: [
18
+ /* @__PURE__ */ t("input", { "data-testid": "text-input", type: "text" }),
19
+ /* @__PURE__ */ t("button", { "data-testid": "submit-button", type: "submit", children: "Submit" })
20
+ ] })
21
+ );
22
+ const n = i.getByTestId("text-input");
23
+ await e.click(n);
24
+ const o = r.keyDown(n, { key: "Enter" });
25
+ s(o).toBe(!1);
26
+ }), c("allows Enter key press on submit button (does not prevent default)", async () => {
27
+ u(
28
+ /* @__PURE__ */ a(p, { children: [
29
+ /* @__PURE__ */ t("input", { type: "text" }),
30
+ /* @__PURE__ */ t("button", { "data-testid": "submit-button", type: "submit", children: "Submit" })
31
+ ] })
32
+ );
33
+ const e = i.getByTestId("submit-button");
34
+ e.focus();
35
+ const n = r.keyDown(e, { key: "Enter" });
36
+ s(n).toBe(!0);
37
+ }), c("allows Enter key press on regular button (does not prevent default)", async () => {
38
+ const e = l.fn();
39
+ u(
40
+ /* @__PURE__ */ a(p, { children: [
41
+ /* @__PURE__ */ t("input", { type: "text" }),
42
+ /* @__PURE__ */ t("button", { "data-testid": "cancel-button", type: "button", onClick: e, children: "Cancel" })
43
+ ] })
44
+ );
45
+ const n = i.getByTestId("cancel-button");
46
+ n.focus();
47
+ const o = r.keyDown(n, { key: "Enter" });
48
+ s(o).toBe(!0);
49
+ }), c("allows Enter key press on textarea (does not prevent default)", async () => {
50
+ u(
51
+ /* @__PURE__ */ a(p, { children: [
52
+ /* @__PURE__ */ t("input", { type: "text" }),
53
+ /* @__PURE__ */ t("textarea", { "data-testid": "textarea" }),
54
+ /* @__PURE__ */ t("button", { type: "submit", children: "Submit" })
55
+ ] })
56
+ );
57
+ const e = i.getByTestId("textarea");
58
+ e.focus();
59
+ const n = r.keyDown(e, { key: "Enter" });
60
+ s(n).toBe(!0);
61
+ }), c("does not interfere with other key presses", async () => {
62
+ const e = y.setup();
63
+ u(
64
+ /* @__PURE__ */ a(p, { children: [
65
+ /* @__PURE__ */ t("input", { "data-testid": "text-input", type: "text" }),
66
+ /* @__PURE__ */ t("button", { type: "submit", children: "Submit" })
67
+ ] })
68
+ );
69
+ const n = i.getByTestId("text-input");
70
+ await e.click(n), await e.keyboard("a"), await e.keyboard("{Tab}"), await e.keyboard("{Escape}"), s(n).toHaveValue("a");
71
+ const o = r.keyDown(n, { key: "Tab" }), d = r.keyDown(n, { key: "Escape" });
72
+ s(o).toBe(!0), s(d).toBe(!0);
73
+ }), c("prevents Enter key on various input types", async () => {
74
+ u(
75
+ /* @__PURE__ */ a(p, { children: [
76
+ /* @__PURE__ */ t("input", { "data-testid": "input1", type: "text" }),
77
+ /* @__PURE__ */ t("input", { "data-testid": "input2", type: "email" }),
78
+ /* @__PURE__ */ t("input", { "data-testid": "input3", type: "password" }),
79
+ /* @__PURE__ */ t("input", { "data-testid": "input4", type: "number" }),
80
+ /* @__PURE__ */ t("button", { type: "submit", children: "Submit" })
81
+ ] })
82
+ );
83
+ const e = ["input1", "input2", "input3", "input4"];
84
+ for (const n of e) {
85
+ const o = i.getByTestId(n);
86
+ o.focus();
87
+ const d = r.keyDown(o, { key: "Enter" });
88
+ s(d).toBe(!1);
89
+ }
90
+ });
91
+ });
@@ -1,36 +1,37 @@
1
- import { jsx as r } from "react/jsx-runtime";
1
+ import { jsx as o } from "react/jsx-runtime";
2
2
  import { I as i } from "../../index.es-Kg9soDed.js";
3
3
  import { T as l } from "../../index.es-CUuzYysw.js";
4
4
  import '../../assets/SearchBar.css';const u = "_searchbar_gnvwc_1", b = {
5
5
  searchbar: u
6
- }, p = ({
7
- className: o = "",
6
+ }, f = ({
7
+ className: r = "",
8
8
  dense: n = !1,
9
- searchTerm: a,
10
- setSearchTerm: t,
11
- placeholder: s,
12
- fullWidth: e = !0
13
- }) => /* @__PURE__ */ r(
9
+ searchTerm: t,
10
+ setSearchTerm: a,
11
+ placeholder: e,
12
+ fullWidth: s = !0
13
+ }) => /* @__PURE__ */ o(
14
14
  l,
15
15
  {
16
16
  "data-testid": "search-bar-input",
17
- className: `${o ?? ""} ${b.searchbar}`,
17
+ className: `${r ?? ""} ${b.searchbar}`,
18
18
  dense: n,
19
19
  variant: "outlined",
20
- placeholder: s,
21
- value: a,
22
- onChange: (c) => t(c.target.value),
23
- fullWidth: e,
24
- trailingIcon: /* @__PURE__ */ r(
20
+ placeholder: e,
21
+ value: t,
22
+ onChange: (c) => a(c.target.value),
23
+ fullWidth: s,
24
+ trailingIcon: /* @__PURE__ */ o(
25
25
  i,
26
26
  {
27
27
  "data-testid": "search-bar-icon-button",
28
- icon: a ? "close" : "search",
29
- onClick: () => a ? t("") : void 0
28
+ icon: t ? "close" : "search",
29
+ onClick: () => t ? a("") : void 0,
30
+ type: "button"
30
31
  }
31
32
  )
32
33
  }
33
34
  );
34
35
  export {
35
- p as SearchBar
36
+ f as SearchBar
36
37
  };
package/dist/main.d.ts CHANGED
@@ -39,6 +39,7 @@ export { FormSelect } from './components/FormComponents/FormSelect/FormSelect';
39
39
  export { FormSlider } from './components/FormComponents/FormSlider/FormSlider';
40
40
  export { FormText } from './components/FormComponents/FormText/FormText';
41
41
  export { FormToggle } from './components/FormComponents/FormToggle/FormToggle';
42
+ export { SafeForm } from './components/SafeForm/SafeForm';
42
43
  export { AvailableCustomIcons } from './enums/AvailableCustomIcons';
43
44
  export { ThemeColor } from './enums/ThemeColor';
44
45
  export { useBreakpoints } from './hooks/useBreakpoints';
@@ -54,6 +55,6 @@ export type { FilterData, FilterOption, FilterSelection } from './types/Filter';
54
55
  export type { CellTemplate, CellTemplateProps, TableLayoutProps } from './types/GenericTable';
55
56
  export type { HashTab } from './types/HashTab';
56
57
  export type { BaseListElement, ListElement } from './types/ListElement';
57
- export { DATE_FORMAT, TIME_FORMAT, DATE_TIME_FORMAT } from './types/Time';
58
+ export { DATE_FORMAT, DATE_TIME_FORMAT, TIME_FORMAT } from './types/Time';
58
59
  export { AVAILABLE_COUNTRY_KEYS, AVAILABLE_LOCALES, ENGLISH_LANGUAGE_ID, GERMAN_LANGUAGE_ID, LANGUAGE_CODES_MAPPER, LANGUAGE_ID_MAPPER, SPANISH_LANGUAGE_ID, TURKISH_LANGUAGE_ID, } from './types/Languages';
59
60
  export type { AVAILABLE_LANGUAGE_CODES, LANGUAGE_COUNTRY_CODES } from './types/Languages';
package/dist/main.js CHANGED
@@ -5,9 +5,9 @@ import { BasicHeading as a } from "./components/BasicHeading/BasicHeading.js";
5
5
  import { BlockView as A } from "./components/BlockView/BlockView.js";
6
6
  import { ChipCard as n } from "./components/ChipCard/ChipCard.js";
7
7
  import { ContextMenu as E } from "./components/ContextMenu/ContextMenu.js";
8
- import { DeleteModal as L } from "./components/DeleteModal/DeleteModal.js";
8
+ import { DeleteModal as c } from "./components/DeleteModal/DeleteModal.js";
9
9
  import { DetailContentWrapper as _ } from "./components/DetailContentWrapper/DetailContentWrapper.js";
10
- import { Disclaimer as F } from "./components/Disclaimer/Disclaimer.js";
10
+ import { Disclaimer as s } from "./components/Disclaimer/Disclaimer.js";
11
11
  import { EmptyView as G } from "./components/EmptyView/EmptyView.js";
12
12
  import { Filter as D } from "./components/Filter/Filter.js";
13
13
  import { FormattedNumberDisplay as M } from "./components/FormattedNumberDisplay/FormattedNumberDisplay.js";
@@ -31,56 +31,57 @@ import { StepperHeader as xr } from "./components/Stepper/components/StepperHead
31
31
  import { StepperIndicator as ir } from "./components/Stepper/components/StepperIndicator.js";
32
32
  import { Stepper as lr } from "./components/Stepper/Stepper.js";
33
33
  import { VerticalDivider as dr } from "./components/VerticalDivider/VerticalDivider.js";
34
- import { FormCheckBox as cr } from "./components/FormComponents/FormCheckBox/FormCheckBox.js";
35
- import { FormDatePicker as Sr } from "./components/FormComponents/FormDatePicker/FormDatePicker.js";
36
- import { FormNumber as sr } from "./components/FormComponents/FormNumber/FormNumber.js";
34
+ import { FormCheckBox as Sr } from "./components/FormComponents/FormCheckBox/FormCheckBox.js";
35
+ import { FormDatePicker as Lr } from "./components/FormComponents/FormDatePicker/FormDatePicker.js";
36
+ import { FormNumber as Fr } from "./components/FormComponents/FormNumber/FormNumber.js";
37
37
  import { FormRadio as Tr } from "./components/FormComponents/FormRadio/FormRadio.js";
38
38
  import { FormSelect as Ir } from "./components/FormComponents/FormSelect/FormSelect.js";
39
39
  import { FormSlider as Nr } from "./components/FormComponents/FormSlider/FormSlider.js";
40
40
  import { FormText as gr } from "./components/FormComponents/FormText/FormText.js";
41
41
  import { FormToggle as Cr } from "./components/FormComponents/FormToggle/FormToggle.js";
42
- import { AvailableCustomIcons as br } from "./enums/AvailableCustomIcons.js";
43
- import { ThemeColor as Rr } from "./enums/ThemeColor.js";
44
- import { u as Ur } from "./useBreakpoints-MzTZ0tCT.js";
45
- import { capitalizeFirstLetters as hr, getFormattedDateTime as Pr, getNumberAsLocaleString as kr, trimLeadingAndTrailingSpaces as wr } from "./services/UtilService.js";
46
- import { DATE_FORMAT as yr, DATE_TIME_FORMAT as Yr, TIME_FORMAT as Kr } from "./types/Time.js";
47
- import { AVAILABLE_COUNTRY_KEYS as Wr, AVAILABLE_LOCALES as Xr, ENGLISH_LANGUAGE_ID as jr, GERMAN_LANGUAGE_ID as qr, LANGUAGE_CODES_MAPPER as Jr, LANGUAGE_ID_MAPPER as Qr, SPANISH_LANGUAGE_ID as Zr, TURKISH_LANGUAGE_ID as $r } from "./types/Languages.js";
42
+ import { SafeForm as br } from "./components/SafeForm/SafeForm.js";
43
+ import { AvailableCustomIcons as Rr } from "./enums/AvailableCustomIcons.js";
44
+ import { ThemeColor as Ur } from "./enums/ThemeColor.js";
45
+ import { u as hr } from "./useBreakpoints-MzTZ0tCT.js";
46
+ import { capitalizeFirstLetters as kr, getFormattedDateTime as wr, getNumberAsLocaleString as vr, trimLeadingAndTrailingSpaces as yr } from "./services/UtilService.js";
47
+ import { DATE_FORMAT as Kr, DATE_TIME_FORMAT as zr, TIME_FORMAT as Wr } from "./types/Time.js";
48
+ import { AVAILABLE_COUNTRY_KEYS as jr, AVAILABLE_LOCALES as qr, ENGLISH_LANGUAGE_ID as Jr, GERMAN_LANGUAGE_ID as Qr, LANGUAGE_CODES_MAPPER as Zr, LANGUAGE_ID_MAPPER as $r, SPANISH_LANGUAGE_ID as ro, TURKISH_LANGUAGE_ID as oo } from "./types/Languages.js";
48
49
  export {
49
- Wr as AVAILABLE_COUNTRY_KEYS,
50
- Xr as AVAILABLE_LOCALES,
50
+ jr as AVAILABLE_COUNTRY_KEYS,
51
+ qr as AVAILABLE_LOCALES,
51
52
  e as AlertBanner,
52
- br as AvailableCustomIcons,
53
+ Rr as AvailableCustomIcons,
53
54
  f as BaseView,
54
55
  a as BasicHeading,
55
56
  A as BlockView,
56
57
  n as ChipCard,
57
58
  E as ContextMenu,
58
- yr as DATE_FORMAT,
59
- Yr as DATE_TIME_FORMAT,
60
- L as DeleteModal,
59
+ Kr as DATE_FORMAT,
60
+ zr as DATE_TIME_FORMAT,
61
+ c as DeleteModal,
61
62
  _ as DetailContentWrapper,
62
- F as Disclaimer,
63
- jr as ENGLISH_LANGUAGE_ID,
63
+ s as Disclaimer,
64
+ Jr as ENGLISH_LANGUAGE_ID,
64
65
  G as EmptyView,
65
66
  D as Filter,
66
- cr as FormCheckBox,
67
- Sr as FormDatePicker,
68
- sr as FormNumber,
67
+ Sr as FormCheckBox,
68
+ Lr as FormDatePicker,
69
+ Fr as FormNumber,
69
70
  Tr as FormRadio,
70
71
  Ir as FormSelect,
71
72
  Nr as FormSlider,
72
73
  gr as FormText,
73
74
  Cr as FormToggle,
74
75
  M as FormattedNumberDisplay,
75
- qr as GERMAN_LANGUAGE_ID,
76
+ Qr as GERMAN_LANGUAGE_ID,
76
77
  B as GenericTable,
77
78
  O as HashTabView,
78
79
  u as HeaderFilter,
79
80
  H as HealthCheckFailed,
80
81
  V as Iconify,
81
82
  P as InfoGroup,
82
- Jr as LANGUAGE_CODES_MAPPER,
83
- Qr as LANGUAGE_ID_MAPPER,
83
+ Zr as LANGUAGE_CODES_MAPPER,
84
+ $r as LANGUAGE_ID_MAPPER,
84
85
  m as LinkBanner,
85
86
  w as ListArea,
86
87
  y as LoadingSpinner,
@@ -89,7 +90,8 @@ export {
89
90
  j as OfflineView,
90
91
  J as OnboardingBanner,
91
92
  Z as OverflowTooltip,
92
- Zr as SPANISH_LANGUAGE_ID,
93
+ ro as SPANISH_LANGUAGE_ID,
94
+ br as SafeForm,
93
95
  rr as ScrollbarX,
94
96
  or as ScrollbarY,
95
97
  tr as SearchBar,
@@ -97,13 +99,13 @@ export {
97
99
  lr as Stepper,
98
100
  xr as StepperHeader,
99
101
  ir as StepperIndicator,
100
- Kr as TIME_FORMAT,
101
- $r as TURKISH_LANGUAGE_ID,
102
- Rr as ThemeColor,
102
+ Wr as TIME_FORMAT,
103
+ oo as TURKISH_LANGUAGE_ID,
104
+ Ur as ThemeColor,
103
105
  dr as VerticalDivider,
104
- hr as capitalizeFirstLetters,
105
- Pr as getFormattedDateTime,
106
- kr as getNumberAsLocaleString,
107
- wr as trimLeadingAndTrailingSpaces,
108
- Ur as useBreakpoints
106
+ kr as capitalizeFirstLetters,
107
+ wr as getFormattedDateTime,
108
+ vr as getNumberAsLocaleString,
109
+ yr as trimLeadingAndTrailingSpaces,
110
+ hr as useBreakpoints
109
111
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hortiview/shared-components",
3
3
  "description": "This is a shared component library. It should used in the HortiView platform and its modules.",
4
- "version": "2.7.0",
4
+ "version": "2.8.0",
5
5
  "type": "module",
6
6
  "repository": "https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared",
7
7
  "author": "Falk Menge <falk.menge.ext@bayer.com>",