@hortiview/shared-components 2.29.0-alpha.df46fcc5.1 → 2.30.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,4 +1,34 @@
1
- ## [2.29.0-alpha.df46fcc5.1](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.28.0...v2.29.0-alpha.df46fcc5.1) (2026-07-21)
1
+ ## [2.30.0](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.29.0...v2.30.0) (2026-07-29)
2
+
3
+ ### Features
4
+
5
+ * add constrained height option and enhanced max-height behavior for GenericTable, improve resizable column handling, and update sticky column z-index styles ([7523e1c](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/7523e1c08649277473d2cf5732c05828cad49c55))
6
+ * add large icon font-size fix ([93e0332](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/93e03323297b6ec38f935ed8dd6c5fb4fcb9529a))
7
+ * add resizable and sticky column functionality to GenericTable, update docs and styles ([4b1fc39](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/4b1fc39483626e4da698a4e01e75ab4e406b0f0e))
8
+ * change filter icon ([8f0ba94](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/8f0ba941e5cf532e60839aa2735f57a69af4ac12))
9
+ * enhance GenericTable with resizable column keys, no-border option, and updated styles ([a3efed8](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/a3efed82a5e1606e5ae2ae09e5d6cc72c8e897a1))
10
+ * enhance Modal with better footerSupplemental and action alignment styling, clsx refactor ([a682aaf](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/a682aafec611d4011f3256d4b1981a12d997c2b4))
11
+ * replace season-end icon with new version ([76957d3](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/76957d3541b0b793daa22808b7163d3f3c8932d2))
12
+ * update GenericTable styles for better sticky header and column handling, remove unused scrollWrapper styling ([5d95a74](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/5d95a74a9ada59333a6357c599d575a183fadfed))
13
+
14
+ ### Bug Fixes
15
+
16
+ * appply PR suggestions; icon color, style comments, docs ([c319f59](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/c319f59a41ccb78375261ad5282e05901e0361cf))
17
+ * style overrride for the sticky actions header ([7d71668](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/7d716684a7b53b8b8c4d1bb08e3c512ab750c4de))
18
+ * update fallback offsetHeight in GenericTable pagination calculation to prevent layout issues ([38128e5](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/38128e521590675c1787291dbe420f88def4d438))
19
+ * use currentColor for svg fill ([0a7cb31](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/0a7cb3152b7a6e1dd3b076c0fb5ce411b1ef3473))
20
+
21
+ ### Documentation
22
+
23
+ * generic table dynamic height calculations ([2927482](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/2927482853b12d57b921719ba642fe29991280fd))
24
+
25
+ ### Code Refactoring
26
+
27
+ * deprecate `tableElevationLevel`, update table styles, and remove unused code ([9086f5f](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/9086f5f2ef481a2da3d8f3b345295040b6c781cf))
28
+ * remove unnecessary overflow-y styling updates in GenericTable maxHeight logic ([f339105](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/f339105a7fcef87583eb19fdd85ffeb2af7aadd6))
29
+ * update filterButtonSize control to use select with options ([589bfa5](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/589bfa5c7dbc72632dd12177f21842f3be7ce17c))
30
+
31
+ ## [2.29.0](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.28.3...v2.29.0) (2026-07-22)
2
32
 
3
33
  ### Features
4
34
 
@@ -6,9 +36,35 @@
6
36
 
7
37
  ### Code Refactoring
8
38
 
9
- * add additional type exports to main ([b9db9ef](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/b9db9ef2dda1f20afd80cd46c741e4c73b9c7fd5))
10
39
  * update yarnrc ([e510d88](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/e510d88d94d7b9a7d5c94e60a85dc01985745bb7))
11
40
 
41
+ ## [2.28.3](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.28.2...v2.28.3) (2026-07-17)
42
+
43
+ ### Bug Fixes
44
+
45
+ * close context menu on scroll and allow passing more props ([389de23](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/389de23e690f3cafe9724bafb1bb08e09ca33eec))
46
+ * handle repositioning of hoisted ContextMenu on scroll ([1f8025a](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/1f8025a545946014c0dd80f6982611c58c07fc29))
47
+
48
+ ### Documentation
49
+
50
+ * update ContextMenu prop documentation ([c0d063c](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/c0d063c62ab3cad6c2b6f498d4241c4f8aeb8823))
51
+
52
+ ### Code Refactoring
53
+
54
+ * remove hoistToBody prop and update context menu story for clarity ([d1155bc](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/d1155bcf18753ee7029a166421bf08820692482d))
55
+
56
+ ## [2.28.2](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.28.1...v2.28.2) (2026-07-17)
57
+
58
+ ### Bug Fixes
59
+
60
+ * handle null and undefined values in CustomTextField and enhance FormNumber tests ([819db7e](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/819db7ee8dded41e96423c799c19de26e82742f0))
61
+
62
+ ## [2.28.1](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.28.0...v2.28.1) (2026-07-06)
63
+
64
+ ### Code Refactoring
65
+
66
+ * add additional type exports to main ([b9db9ef](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/commit/b9db9ef2dda1f20afd80cd46c741e4c73b9c7fd5))
67
+
12
68
  ## [2.28.0](https://sdundc.visualstudio.com/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.27.4...v2.28.0) (2026-07-06)
13
69
 
14
70
  ### Features
@@ -0,0 +1,98 @@
1
+ import { jsx as u } from "react/jsx-runtime";
2
+ import { useMemo as p } from "react";
3
+ import { ContextMenu as q } from "./components/ContextMenu/ContextMenu.js";
4
+ import './assets/GenericTableService.css';const g = "_topBar_7lsq9_1", B = "_leadingContent_7lsq9_5", v = "_filterBar_7lsq9_9", x = "_rowActions_7lsq9_14", y = "_start_7lsq9_20", C = "_emptyTable_7lsq9_25", A = "_tableContainer_7lsq9_33", m = "_table_7lsq9_33", w = "_noBorder_7lsq9_47", z = "_fullWidth_7lsq9_75", P = "_hasActions_7lsq9_104", F = "_resizable_7lsq9_112", I = "_stickyColumns_7lsq9_112", L = "_stickyFirst_7lsq9_113", N = "_stickyLast_7lsq9_114", j = {
5
+ topBar: g,
6
+ leadingContent: B,
7
+ filterBar: v,
8
+ rowActions: x,
9
+ start: y,
10
+ emptyTable: C,
11
+ tableContainer: A,
12
+ table: m,
13
+ noBorder: w,
14
+ fullWidth: z,
15
+ hasActions: P,
16
+ resizable: F,
17
+ stickyColumns: I,
18
+ stickyFirst: L,
19
+ stickyLast: N
20
+ }, K = ({
21
+ data: t = [],
22
+ order: s = [],
23
+ cellTemplates: e = void 0,
24
+ headerTranslation: r = (_) => _,
25
+ getRowActions: i = void 0,
26
+ customColumnWidth: o,
27
+ cardTitleColumn: c,
28
+ cardSubTitleColumn: a,
29
+ stickyColumns: f,
30
+ resizableColumns: d = []
31
+ }) => p(() => {
32
+ if (t?.length === 0) return [];
33
+ const _ = M(t[0], s).map((n) => {
34
+ const l = o ? o[n] : void 0, b = d ? d.includes(n) : !1;
35
+ return {
36
+ id: n,
37
+ header: r(n),
38
+ accessor: n,
39
+ cellTemplate: e ? e[n] : void 0,
40
+ cellProps: l ? { width: l } : void 0,
41
+ headerCellProps: l ? { width: l } : void 0,
42
+ asCardTitle: n === c,
43
+ asCardSubtitle: n === a,
44
+ disableResizing: !b,
45
+ width: Number.isInteger(l) ? Number(l) : 150
46
+ };
47
+ }), h = i ? [
48
+ ..._,
49
+ {
50
+ id: "actions",
51
+ header: " ",
52
+ accessor: "actions",
53
+ cellProps: { id: "actions" },
54
+ headerCellProps: { id: "actions" },
55
+ disableResizing: !0,
56
+ width: 64
57
+ // 4rem
58
+ }
59
+ ] : _;
60
+ return G(h, f);
61
+ }, [
62
+ t,
63
+ s,
64
+ i,
65
+ f,
66
+ o,
67
+ r,
68
+ e,
69
+ c,
70
+ a,
71
+ d
72
+ ]), G = (t, s) => !s?.first && !s?.last || t.length === 0 ? t : t.map((e, r) => r === 0 && s?.first ? {
73
+ ...e,
74
+ fixed: "leading"
75
+ } : r === t.length - 1 && s?.last ? {
76
+ ...e,
77
+ fixed: "trailing"
78
+ } : e), S = ({
79
+ data: t = [],
80
+ getRowActions: s = void 0
81
+ }) => p(() => s ? t.map((e) => {
82
+ const r = s(e);
83
+ if (!r || r.length === 0) return e;
84
+ const i = /* @__PURE__ */ u("div", { className: j.rowActions, children: /* @__PURE__ */ u(q, { hoistToBody: !0, actions: r, iconOrientation: "horizontal" }) });
85
+ return { ...e, actions: i };
86
+ }) : t, [t, s]), M = (t, s) => {
87
+ if (!t) return [];
88
+ let e = Object.keys(t).map((r) => r);
89
+ return s?.length > 0 && (e = e.sort((r, i) => {
90
+ const o = s.findIndex((a) => a === r), c = s.findIndex((a) => a === i);
91
+ return o === -1 ? 1 : c === -1 ? -1 : o - c;
92
+ })), e;
93
+ };
94
+ export {
95
+ S as a,
96
+ j as s,
97
+ K as u
98
+ };
@@ -0,0 +1 @@
1
+ ._largeIconFix_10hc4_1 i[class*=lmnt-icon--large]{font-size:32px}
package/assets/Filter.css CHANGED
@@ -1 +1 @@
1
- ._filterButton_1qtzn_1{width:15rem;height:100%!important;margin:0;border-radius:.25rem!important}._filterButton_1qtzn_1,._filterButton_1qtzn_1:hover,._filterButton_1qtzn_1:focus,._filterButton_1qtzn_1:active,._filterButton_1qtzn_1:target,._filterButton_1qtzn_1 [class^=mdc-button__ripple],._filterButton_1qtzn_1:hover [class^=mdc-button__ripple],._filterButton_1qtzn_1:focus [class^=mdc-button__ripple],._filterButton_1qtzn_1:active [class^=mdc-button__ripple],._filterButton_1qtzn_1:target [class^=mdc-button__ripple]{border-radius:.25rem!important}._relativeParent_1qtzn_21{position:relative}._iconColor_1qtzn_25{color:var(--lmnt-theme-primary)}._filterBadge_1qtzn_29{position:absolute;top:0;right:0;transform:translate(50%,-50%)}._dense_1qtzn_36,._dense_1qtzn_36 div[class*=lmnt-select__anchor]{height:2.5rem!important}._filterModal_1qtzn_41 [class="lmnt-modal__actions mdc-dialog__actions"]{margin-bottom:0!important}._borderRadius_1qtzn_45 [class*=mdc-notched-outline__leading]{border-radius:.25rem 0 0 .25rem!important}._borderRadius_1qtzn_45 [class*=mdc-notched-outline__trailing]{border-radius:0 .25rem .25rem 0!important}
1
+ ._filterButton_1qsua_1{width:15rem;height:100%!important;margin:0;border-radius:.25rem!important}._filterButton_1qsua_1,._filterButton_1qsua_1:hover,._filterButton_1qsua_1:focus,._filterButton_1qsua_1:active,._filterButton_1qsua_1:target,._filterButton_1qsua_1 [class^=mdc-button__ripple],._filterButton_1qsua_1:hover [class^=mdc-button__ripple],._filterButton_1qsua_1:focus [class^=mdc-button__ripple],._filterButton_1qsua_1:active [class^=mdc-button__ripple],._filterButton_1qsua_1:target [class^=mdc-button__ripple]{border-radius:.25rem!important}._relativeParent_1qsua_21{position:relative}._iconColor_1qsua_25{color:var(--lmnt-theme-primary)}._largeIconFix_1qsua_29 i[class*=lmnt-icon--large]{font-size:32px}._filterBadge_1qsua_33{position:absolute;top:0;right:0;transform:translate(50%,-50%)}._dense_1qsua_40,._dense_1qsua_40 div[class*=lmnt-select__anchor]{height:2.5rem!important}._filterModal_1qsua_45 [class="lmnt-modal__actions mdc-dialog__actions"]{margin-bottom:0!important}._borderRadius_1qsua_49 [class*=mdc-notched-outline__leading]{border-radius:.25rem 0 0 .25rem!important}._borderRadius_1qsua_49 [class*=mdc-notched-outline__trailing]{border-radius:0 .25rem .25rem 0!important}
@@ -0,0 +1 @@
1
+ ._topBar_7lsq9_1 [class*=lmnt-table__top-bar__title]{display:none}._leadingContent_7lsq9_5{padding:.5rem 1rem}._filterBar_7lsq9_9{padding:unset;width:inherit!important}._rowActions_7lsq9_14{width:4rem;display:flex;justify-content:center}._start_7lsq9_20{padding-top:0;padding-bottom:0}._emptyTable_7lsq9_25{height:16rem}[class*=mnt-pagination][class*=mdc-data-table__pagination]{border-top:1px solid var(--lmnt-theme-on-secondary-stroke)}._tableContainer_7lsq9_33{display:contents}._elevation_7lsq9_37{border-radius:.4rem;width:100%}._elevation_7lsq9_37._noShadow_7lsq9_42{box-shadow:none!important;border-radius:0}._table_7lsq9_33._noBorder_7lsq9_47{border:none}._table_7lsq9_33,._table_7lsq9_33 [class*=mdc-data-table__table-container]{border-radius:.4rem}._table_7lsq9_33 *[id=actions]{width:44px;padding:0 2px;position:sticky;right:0;background-color:var(--lmnt-theme-background)}._table_7lsq9_33 tr:hover td[id=actions]{background-color:var(--table-bg-color-hover)}._noBorder_7lsq9_47{border:none}._fullWidth_7lsq9_75{width:100%}._table_7lsq9_33 [class*=mdc-data-table__row],._table_7lsq9_33 [class*=mdc-data-table__header-row]{width:-webkit-fill-available!important}._table_7lsq9_33 [class*=lmnt-table__header]{position:sticky;top:0;z-index:2!important;background-color:var(--lmnt-theme-background)}._table_7lsq9_33 [class*=lmnt-table__table]{min-width:max-content;width:100%}._table_7lsq9_33 [class*=mdc-data-table__row]>div:not(:last-child),._table_7lsq9_33 [class*=mdc-data-table__header-row]>div:not(:last-child){min-width:4.5rem}._table_7lsq9_33._hasActions_7lsq9_104 [class*=mdc-data-table__row]>div:last-child,._table_7lsq9_33._hasActions_7lsq9_104 [class*=mdc-data-table__header-row]>div:last-child{min-width:4rem}._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112 [class*=mdc-data-table__row]>div:not(:first-child):not(:last-child),._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112:not(._stickyFirst_7lsq9_113) [class*=mdc-data-table__row]>div:first-child,._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112:not(._stickyLast_7lsq9_114) [class*=mdc-data-table__row]>div:last-child{width:unset!important;flex:1!important;min-width:9.375rem}._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112 [class*=mdc-data-table__header-row]>div:not(:first-child):not(:last-child),._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112:not(._stickyFirst_7lsq9_113) [class*=mdc-data-table__header-row]>div:first-child,._table_7lsq9_33._resizable_7lsq9_112._stickyColumns_7lsq9_112:not(._stickyLast_7lsq9_114) [class*=mdc-data-table__header-row]>div:last-child{width:unset!important;flex:1!important;min-width:9.375rem}._table_7lsq9_33._stickyFirst_7lsq9_113 [class*=mdc-data-table__cell]:first-child,._table_7lsq9_33._stickyFirst_7lsq9_113 [class*=mdc-data-table__header-cell]:first-child{position:sticky!important;left:0;z-index:1!important;background-color:var(--lmnt-theme-background)}._table_7lsq9_33._stickyFirst_7lsq9_113 [class*=mdc-data-table__header-cell]:first-child{z-index:3!important}._table_7lsq9_33._stickyLast_7lsq9_114 [class*=mdc-data-table__cell]:last-child,._table_7lsq9_33._stickyLast_7lsq9_114 [class*=mdc-data-table__header-cell]:last-child{position:sticky!important;right:0;z-index:1!important;background-color:var(--lmnt-theme-background)}._table_7lsq9_33._stickyLast_7lsq9_114 [class*=mdc-data-table__header-cell]:last-child{z-index:3!important}._table_7lsq9_33._stickyFirst_7lsq9_113 tr:hover td:first-child,._table_7lsq9_33._stickyLast_7lsq9_114 tr:hover td:last-child{background-color:var(--table-bg-color-hover)}._table_7lsq9_33._resizable_7lsq9_112 [class*=lmnt-table__resize-handle]{border-left:.5rem solid transparent;border-right:.5rem solid transparent}._table_7lsq9_33 div[id=actions]{position:sticky!important}
package/assets/Modal.css CHANGED
@@ -1 +1 @@
1
- ._modal_1l955_1{z-index:75}._modal_1l955_1 div[class*=lmnt-modal__surface]{max-height:100svh!important;max-width:100svw!important}._modal_1l955_1 div:not([class*=mdc-dialog--fullscreen]) div[class*=lmnt-modal__surface]{border-radius:1rem!important}._modal_1l955_1 footer{margin-bottom:0!important}._gap_1l955_18{gap:4px!important;padding-left:.5rem!important}._title_1l955_23{header{display:flex;justify-content:start;padding-inline:0!important;>div{width:100%;margin-left:0!important}}}._titleWithoutCloseIcon_1l955_36{margin-left:1rem!important}._closeButton_1l955_40{color:var(--lmnt-theme-on-surface-inactive)}._closeButton_1l955_40:before{display:none!important}._closeButton_1l955_40:hover{background-color:var(--lmnt-theme-surface-variant)!important}._errorBanner_1l955_52{width:100%}._headerActions_1l955_56{margin-left:.5rem}
1
+ ._modal_3lh36_1{z-index:75}._modal_3lh36_1 div[class*=lmnt-modal__surface]{max-height:100svh!important;max-width:100svw!important}._modal_3lh36_1 div:not([class*=mdc-dialog--fullscreen]) div[class*=lmnt-modal__surface]{border-radius:1rem!important}._modal_3lh36_1 footer{margin-bottom:0!important}._gap_3lh36_18{gap:4px!important;padding-left:.5rem!important}._title_3lh36_23{header{display:flex;justify-content:start;padding-inline:0!important;>div{width:100%;margin-left:0!important}}}._titleWithoutCloseIcon_3lh36_36{margin-left:1rem!important}._closeButton_3lh36_40{color:var(--lmnt-theme-on-surface-inactive)}._closeButton_3lh36_40:before{display:none!important}._closeButton_3lh36_40:hover{background-color:var(--lmnt-theme-surface-variant)!important}._errorBanner_3lh36_52{width:100%}._headerActions_3lh36_56{margin-left:.5rem}._footerLayoutFixes_3lh36_66{footer[class*=lmnt-modal__actions]{justify-content:space-between!important;padding:0 .75rem .25rem}div[class*=lmnt-modal_actions_button]{margin:unset!important}}
@@ -1,26 +1,29 @@
1
- import { jsx as o } from "react/jsx-runtime";
2
- import { I as s } from "../../index.es-BwhRJBEH.js";
3
- import { Allowed as a } from "../Allowed/Allowed.js";
4
- const u = ({
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { I as d } from "../../index.es-BwhRJBEH.js";
3
+ import { Allowed as s } from "../Allowed/Allowed.js";
4
+ import '../../assets/AllowedIconButton.css';const m = "_largeIconFix_10hc4_1", I = {
5
+ largeIconFix: m
6
+ }, p = ({
5
7
  "data-testid": t,
6
- variant: e = "filled-primary",
7
- iconType: i = "filled",
8
- size: d = "medium",
9
- formId: r,
10
- permissions: l,
11
- entityIds: m,
12
- ...n
13
- }) => /* @__PURE__ */ o(a, { neededPermissions: l, entityIds: m, children: /* @__PURE__ */ o(
14
- s,
8
+ variant: i = "filled-primary",
9
+ iconType: l = "filled",
10
+ size: o = "medium",
11
+ formId: n,
12
+ permissions: r,
13
+ entityIds: a,
14
+ ...c
15
+ }) => /* @__PURE__ */ e(s, { neededPermissions: r, entityIds: a, children: /* @__PURE__ */ e(
16
+ d,
15
17
  {
16
- ...n,
18
+ ...c,
17
19
  "data-testid": `allowed-icon-button-${t}`,
18
- form: r,
19
- iconSize: d,
20
- iconType: i,
21
- variant: e
20
+ className: o === "large" ? I.largeIconFix : "",
21
+ form: n,
22
+ iconSize: o,
23
+ iconType: l,
24
+ variant: i
22
25
  }
23
26
  ) });
24
27
  export {
25
- u as AllowedIconButton
28
+ p as AllowedIconButton
26
29
  };
@@ -1,7 +1,8 @@
1
1
  import { ListItemProps } from '@element-public/react-list';
2
+ import { MenuProps } from '@element-public/react-menu';
2
3
  import { OfflineViewProps } from '../OfflineView/OfflineView';
3
4
  import { IsAllowedProps } from '../PermissionChecks/PermissionService.tsx';
4
- type ContextMenuProps = {
5
+ type ContextMenuProps = MenuProps & {
5
6
  /**
6
7
  * If not null, the menu will be open
7
8
  */
@@ -25,6 +26,10 @@ type ContextMenuProps = {
25
26
  * Props forwarded to <OfflineView /> when offline.
26
27
  */
27
28
  offlineViewProps?: Partial<OfflineViewProps>;
29
+ /**
30
+ * Optional className to apply to the menu container
31
+ */
32
+ className?: string;
28
33
  };
29
34
  export type ActionProps = ListItemProps & {
30
35
  closeOnClick?: boolean;
@@ -54,7 +59,8 @@ export type ActionProps = ListItemProps & {
54
59
  *
55
60
  * @param {boolean} triggerOpen indicates if the menu should be open
56
61
  * @param {ListItemProps[]} actions list of actions to display in the context menu as ListItems
57
- * @param testId id for testing, automatically prefixed
62
+ * @param {'vertical' | 'horizontal'} iconOrientation determines if menu icon should be vertical or horizontal three dots. Default is 'vertical'
63
+ * @param {string} data-testid id for testing, automatically prefixed
58
64
  * @recommended `primaryText`, `onClick`, `leadingBlock`
59
65
  * @requires `ListItemProps` from `@element-public/react-components`
60
66
  * @example const actions = [
@@ -64,7 +70,9 @@ export type ActionProps = ListItemProps & {
64
70
  * ];
65
71
  * @param {boolean} isOnline Whether the user is online; shows OfflineView when false.
66
72
  * @param {OfflineViewProps} offlineViewProps Props forwarded to OfflineView when offline.
73
+ * @param {string} className Optional className to apply to the menu container
74
+ * @param {MenuProps} menuProps Element Menu props, e.g. `hoistToBody`, `themeColor`, etc.
67
75
  * @returns a context menu with the given actions as ListItems
68
76
  */
69
- export declare const ContextMenu: ({ triggerOpen, actions, iconOrientation, "data-testid": dataTestId, isOnline, offlineViewProps, }: ContextMenuProps) => import("react").JSX.Element | null;
77
+ export declare const ContextMenu: ({ triggerOpen, actions, iconOrientation, "data-testid": dataTestId, isOnline, offlineViewProps, className, ...menuProps }: ContextMenuProps) => import("react").JSX.Element | null;
70
78
  export {};
@@ -1,120 +1,130 @@
1
- import { jsx as i, jsxs as M } from "react/jsx-runtime";
2
- import { I as k } from "../../index.es-BwhRJBEH.js";
3
- import { M as v, L as w, a as x, b as C } from "../../index.es-BIgjyLDa.js";
4
- import { useState as g, useCallback as T, useEffect as I, useMemo as b, Fragment as A, useRef as L, useLayoutEffect as B } from "react";
5
- import { c as V } from "../../index-_-9ybP20.js";
6
- import { u as z } from "../../uniqueId-CJo-XRQb.js";
7
- import { OfflineView as H } from "../OfflineView/OfflineView.js";
8
- import { useIsAllowed as N } from "../PermissionChecks/PermissionService.js";
9
- import { u as O } from "../../useBreakpoints-DDrM9Cfx.js";
10
- import '../../assets/ContextMenu.css';const E = "_menu_52omh_1", R = "_mobile_52omh_7", S = "_desktop_52omh_11", $ = "_icon_52omh_15", j = "_listItem_52omh_19", q = "_offlineViewMargin_52omh_51", D = "_primaryTextTruncated_52omh_55", n = {
11
- menu: E,
12
- mobile: R,
13
- desktop: S,
14
- icon: $,
15
- listItem: j,
16
- offlineViewMargin: q,
17
- primaryTextTruncated: D
18
- }, P = ({
19
- triggerOpen: t = null,
20
- actions: l,
21
- iconOrientation: a = "vertical",
22
- "data-testid": c,
23
- isOnline: m = !0,
24
- offlineViewProps: f
1
+ import { jsx as t, jsxs as L } from "react/jsx-runtime";
2
+ import { I as A } from "../../index.es-BwhRJBEH.js";
3
+ import { M as B, L as O, a as x, b as V } from "../../index.es-BIgjyLDa.js";
4
+ import { c as C } from "../../index-_-9ybP20.js";
5
+ import { u as E } from "../../uniqueId-CJo-XRQb.js";
6
+ import { useState as I, useRef as T, useCallback as M, useEffect as k, useMemo as N, Fragment as R, useLayoutEffect as z } from "react";
7
+ import { u as H } from "../../useBreakpoints-DDrM9Cfx.js";
8
+ import { OfflineView as S } from "../OfflineView/OfflineView.js";
9
+ import { useIsAllowed as $ } from "../PermissionChecks/PermissionService.js";
10
+ import { repositionMenuVertically as j } from "./ContextMenuService.js";
11
+ import '../../assets/ContextMenu.css';const q = "_menu_52omh_1", D = "_mobile_52omh_7", F = "_desktop_52omh_11", G = "_icon_52omh_15", J = "_listItem_52omh_19", K = "_offlineViewMargin_52omh_51", Q = "_primaryTextTruncated_52omh_55", o = {
12
+ menu: q,
13
+ mobile: D,
14
+ desktop: F,
15
+ icon: G,
16
+ listItem: J,
17
+ offlineViewMargin: K,
18
+ primaryTextTruncated: Q
19
+ }, oe = ({
20
+ triggerOpen: n = null,
21
+ actions: u,
22
+ iconOrientation: m = "vertical",
23
+ "data-testid": f,
24
+ isOnline: d = !0,
25
+ offlineViewProps: y,
26
+ className: g,
27
+ ...s
25
28
  }) => {
26
- const { isMobile: d } = O(), [u, o] = g(!1), _ = N(), p = T(() => {
27
- o(!1);
28
- }, []), h = T(() => {
29
- o((e) => !e);
29
+ const { isMobile: w } = H(), [l, c] = I(!1), _ = T(null), a = T(null), r = $(), i = M(() => {
30
+ c(!1);
31
+ }, []), p = M(() => {
32
+ c((e) => !e);
30
33
  }, []);
31
- I(() => {
32
- o(t !== null ? t : !1);
33
- }, [t]);
34
- const r = b(() => l.filter((e) => e.isHidden || e.isAllowed === !1 ? !1 : !(e.permissionConfiguration && !_(e.permissionConfiguration))), [l, _]);
35
- return r.length === 0 ? null : /* @__PURE__ */ i(
36
- v,
34
+ k(() => {
35
+ c(n !== null ? n : !1);
36
+ }, [n]), k(() => {
37
+ if (!l || !s.hoistToBody) return;
38
+ const e = () => {
39
+ j(_.current, a.current) && i();
40
+ };
41
+ return window.addEventListener("scroll", e, !0), () => window.removeEventListener("scroll", e, !0);
42
+ }, [l, i, s.hoistToBody]);
43
+ const b = C(o.menu, g), v = N(() => u.filter((e) => e.isHidden || e.isAllowed === !1 ? !1 : !(e.permissionConfiguration && !r(e.permissionConfiguration))), [u, r]);
44
+ return v.length === 0 ? null : /* @__PURE__ */ t("div", { ref: _, children: /* @__PURE__ */ t(
45
+ B,
37
46
  {
38
- className: n.menu,
39
- "data-testid": c ?? "contextMenu-undefined",
40
- open: u,
47
+ ref: a,
48
+ className: b,
49
+ "data-testid": f ?? "contextMenu-undefined",
50
+ open: l,
41
51
  surfaceOnly: !0,
42
- hoistToBody: !0,
43
- onClose: p,
44
- trigger: /* @__PURE__ */ i(
45
- k,
52
+ onClose: i,
53
+ trigger: /* @__PURE__ */ t(
54
+ A,
46
55
  {
47
- className: n.icon,
48
- variant: u ? "filled-primary" : void 0,
56
+ className: o.icon,
57
+ variant: l ? "filled-primary" : void 0,
49
58
  "data-testid": "open-button",
50
- icon: a === "vertical" ? "more_vert" : "more_horiz",
51
- onClick: h
59
+ icon: m === "vertical" ? "more_vert" : "more_horiz",
60
+ onClick: p
52
61
  }
53
62
  ),
54
- children: m ? /* @__PURE__ */ i(w, { "data-testid": "selection-list", children: r.map((e, s) => /* @__PURE__ */ M(A, { children: [
55
- e.dividerBefore && s !== 0 && /* @__PURE__ */ i(x, {}),
56
- /* @__PURE__ */ i(
57
- F,
63
+ ...s,
64
+ children: d ? /* @__PURE__ */ t(O, { "data-testid": "selection-list", children: v.map((e, h) => /* @__PURE__ */ L(R, { children: [
65
+ e.dividerBefore && h !== 0 && /* @__PURE__ */ t(x, {}),
66
+ /* @__PURE__ */ t(
67
+ U,
58
68
  {
59
69
  actionProps: e,
60
- index: s,
61
- isMobile: d,
62
- closeMenu: p
70
+ index: h,
71
+ isMobile: w,
72
+ closeMenu: i
63
73
  }
64
74
  ),
65
- e.dividerAfter && s !== r.length - 1 && /* @__PURE__ */ i(x, {})
66
- ] }, z(`LI_${e.primaryText?.toString()}_`))) }) : /* @__PURE__ */ i(
67
- H,
75
+ e.dividerAfter && h !== v.length - 1 && /* @__PURE__ */ t(x, {})
76
+ ] }, E(`LI_${e.primaryText?.toString()}_`))) }) : /* @__PURE__ */ t(
77
+ S,
68
78
  {
69
79
  size: "small",
70
80
  variant: "filled",
71
- className: n.offlineViewMargin,
72
- ...f
81
+ className: o.offlineViewMargin,
82
+ ...y
73
83
  }
74
84
  )
75
85
  },
76
- `contextMenu-${c ?? "undefined"}`
77
- );
78
- }, F = ({
79
- actionProps: t,
80
- index: l,
81
- isMobile: a,
82
- closeMenu: c
86
+ `contextMenu-${f ?? "undefined"}`
87
+ ) });
88
+ }, U = ({
89
+ actionProps: n,
90
+ index: u,
91
+ isMobile: m,
92
+ closeMenu: f
83
93
  }) => {
84
- const m = L(null), [f, d] = g(!1), { closeOnClick: u, permissionConfiguration: o, isAllowed: _, isHidden: p, ...h } = t;
85
- return B(() => {
86
- const r = m.current;
87
- if (!r) return;
88
- const e = r.querySelector(
94
+ const d = T(null), [y, g] = I(!1), { closeOnClick: s, permissionConfiguration: w, isAllowed: l, isHidden: c, ..._ } = n;
95
+ return z(() => {
96
+ const a = d.current;
97
+ if (!a) return;
98
+ const r = a.querySelector(
89
99
  "[class*='mdc-list-item__primary-text']"
90
100
  );
91
- if (!e) return;
92
- const s = () => {
93
- d(e.scrollHeight > e.clientHeight);
101
+ if (!r) return;
102
+ const i = () => {
103
+ g(r.scrollHeight > r.clientHeight);
94
104
  };
95
- s();
96
- const y = new ResizeObserver(s);
97
- return y.observe(e), () => {
98
- y.disconnect();
105
+ i();
106
+ const p = new ResizeObserver(i);
107
+ return p.observe(r), () => {
108
+ p.disconnect();
99
109
  };
100
- }, [t.primaryText, a]), /* @__PURE__ */ i(
101
- C,
110
+ }, [n.primaryText, m]), /* @__PURE__ */ t(
111
+ V,
102
112
  {
103
- ref: m,
104
- "data-testid": t["data-testid"] ?? `contextMenu-action-${l}`,
105
- className: V(
106
- n.listItem,
107
- f && n.primaryTextTruncated,
108
- a ? n.mobile : n.desktop
113
+ ref: d,
114
+ "data-testid": n["data-testid"] ?? `contextMenu-action-${u}`,
115
+ className: C(
116
+ o.listItem,
117
+ y && o.primaryTextTruncated,
118
+ m ? o.mobile : o.desktop
109
119
  ),
110
- ...h,
120
+ ..._,
111
121
  leadingBlockType: "icon",
112
122
  onClick: () => {
113
- t?.onClick?.(), u !== !1 && c();
123
+ n?.onClick?.(), s !== !1 && f();
114
124
  }
115
125
  }
116
126
  );
117
127
  };
118
128
  export {
119
- P as ContextMenu
129
+ oe as ContextMenu
120
130
  };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Repositions the menu vertically to stick with the trigger while scrolling.
3
+ * Horizontal scrolling is ignored.
4
+ *
5
+ * @returns `true` if the trigger has scrolled outside the vertical boundary of
6
+ * its nearest scrollable ancestor (or the viewport), otherwise `false`.
7
+ */
8
+ export declare const repositionMenuVertically: (triggerElement: HTMLElement | null, menuElement: HTMLElement | null) => boolean;
@@ -0,0 +1,19 @@
1
+ const c = (e, t) => {
2
+ const o = e?.getBoundingClientRect();
3
+ if (!o || !t) return !1;
4
+ t.style.top = `${o.bottom}px`;
5
+ const l = r(e), n = l ? l.getBoundingClientRect() : { top: 0, bottom: window.innerHeight };
6
+ return o.bottom < n.top || o.top > n.bottom;
7
+ }, r = (e) => {
8
+ let t = e?.parentElement ?? null;
9
+ for (; t; ) {
10
+ const { overflow: o, overflowY: l } = getComputedStyle(t);
11
+ if (/(auto|scroll|overlay)/.test(o + l) && t.scrollHeight > t.clientHeight)
12
+ return t;
13
+ t = t.parentElement;
14
+ }
15
+ return null;
16
+ };
17
+ export {
18
+ c as repositionMenuVertically
19
+ };