@memberjunction/ng-base-forms 6.1.0-edge.2 → 6.1.0-edge.3

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.
Files changed (125) hide show
  1. package/LICENSE +180 -4
  2. package/README.md +4 -1
  3. package/dist/lib/base-form-component.d.ts +93 -3
  4. package/dist/lib/base-form-component.d.ts.map +1 -1
  5. package/dist/lib/base-form-component.js +240 -9
  6. package/dist/lib/base-form-component.js.map +1 -1
  7. package/dist/lib/chrome/base-form-policy.d.ts +26 -0
  8. package/dist/lib/chrome/base-form-policy.d.ts.map +1 -0
  9. package/dist/lib/chrome/base-form-policy.js +9 -0
  10. package/dist/lib/chrome/base-form-policy.js.map +1 -0
  11. package/dist/lib/chrome/clipped-title.d.ts +8 -0
  12. package/dist/lib/chrome/clipped-title.d.ts.map +1 -0
  13. package/dist/lib/chrome/clipped-title.js +18 -0
  14. package/dist/lib/chrome/clipped-title.js.map +1 -0
  15. package/dist/lib/chrome/form-chrome-coordinator.service.d.ts +35 -0
  16. package/dist/lib/chrome/form-chrome-coordinator.service.d.ts.map +1 -0
  17. package/dist/lib/chrome/form-chrome-coordinator.service.js +96 -0
  18. package/dist/lib/chrome/form-chrome-coordinator.service.js.map +1 -0
  19. package/dist/lib/chrome/form-chrome-rail-pref.d.ts +24 -0
  20. package/dist/lib/chrome/form-chrome-rail-pref.d.ts.map +1 -0
  21. package/dist/lib/chrome/form-chrome-rail-pref.js +52 -0
  22. package/dist/lib/chrome/form-chrome-rail-pref.js.map +1 -0
  23. package/dist/lib/chrome/form-chrome.d.ts +59 -0
  24. package/dist/lib/chrome/form-chrome.d.ts.map +1 -0
  25. package/dist/lib/chrome/form-chrome.js +37 -0
  26. package/dist/lib/chrome/form-chrome.js.map +1 -0
  27. package/dist/lib/chrome/load-form-chrome-rules.d.ts +8 -0
  28. package/dist/lib/chrome/load-form-chrome-rules.d.ts.map +1 -0
  29. package/dist/lib/chrome/load-form-chrome-rules.js +70 -0
  30. package/dist/lib/chrome/load-form-chrome-rules.js.map +1 -0
  31. package/dist/lib/chrome/resolve-form-chrome.d.ts +114 -0
  32. package/dist/lib/chrome/resolve-form-chrome.d.ts.map +1 -0
  33. package/dist/lib/chrome/resolve-form-chrome.js +713 -0
  34. package/dist/lib/chrome/resolve-form-chrome.js.map +1 -0
  35. package/dist/lib/container/record-form-container.component.d.ts +170 -6
  36. package/dist/lib/container/record-form-container.component.d.ts.map +1 -1
  37. package/dist/lib/container/record-form-container.component.js +1194 -62
  38. package/dist/lib/container/record-form-container.component.js.map +1 -1
  39. package/dist/lib/explorer-entity-data-grid.component.d.ts +54 -1
  40. package/dist/lib/explorer-entity-data-grid.component.d.ts.map +1 -1
  41. package/dist/lib/explorer-entity-data-grid.component.js +143 -7
  42. package/dist/lib/explorer-entity-data-grid.component.js.map +1 -1
  43. package/dist/lib/form-record-refresh.coordinator.d.ts +27 -0
  44. package/dist/lib/form-record-refresh.coordinator.d.ts.map +1 -0
  45. package/dist/lib/form-record-refresh.coordinator.js +33 -0
  46. package/dist/lib/form-record-refresh.coordinator.js.map +1 -0
  47. package/dist/lib/form-state.interface.d.ts +4 -0
  48. package/dist/lib/form-state.interface.d.ts.map +1 -1
  49. package/dist/lib/form-state.interface.js.map +1 -1
  50. package/dist/lib/form-state.service.d.ts +5 -0
  51. package/dist/lib/form-state.service.d.ts.map +1 -1
  52. package/dist/lib/form-state.service.js +23 -2
  53. package/dist/lib/form-state.service.js.map +1 -1
  54. package/dist/lib/host/entity-form-host.component.d.ts +5 -1
  55. package/dist/lib/host/entity-form-host.component.d.ts.map +1 -1
  56. package/dist/lib/host/entity-form-host.component.js +16 -2
  57. package/dist/lib/host/entity-form-host.component.js.map +1 -1
  58. package/dist/lib/isa-related-panel/isa-related-panel.component.d.ts +6 -2
  59. package/dist/lib/isa-related-panel/isa-related-panel.component.d.ts.map +1 -1
  60. package/dist/lib/isa-related-panel/isa-related-panel.component.js +15 -1
  61. package/dist/lib/isa-related-panel/isa-related-panel.component.js.map +1 -1
  62. package/dist/lib/panel/collapsible-panel.component.d.ts +24 -2
  63. package/dist/lib/panel/collapsible-panel.component.d.ts.map +1 -1
  64. package/dist/lib/panel/collapsible-panel.component.js +104 -10
  65. package/dist/lib/panel/collapsible-panel.component.js.map +1 -1
  66. package/dist/lib/panel-slot/base-form-panel.d.ts +85 -1
  67. package/dist/lib/panel-slot/base-form-panel.d.ts.map +1 -1
  68. package/dist/lib/panel-slot/base-form-panel.js +72 -3
  69. package/dist/lib/panel-slot/base-form-panel.js.map +1 -1
  70. package/dist/lib/panel-slot/collect-form-panel-registrations.d.ts +8 -0
  71. package/dist/lib/panel-slot/collect-form-panel-registrations.d.ts.map +1 -0
  72. package/dist/lib/panel-slot/collect-form-panel-registrations.js +19 -0
  73. package/dist/lib/panel-slot/collect-form-panel-registrations.js.map +1 -0
  74. package/dist/lib/panel-slot/form-contribution.d.ts +79 -0
  75. package/dist/lib/panel-slot/form-contribution.d.ts.map +1 -0
  76. package/dist/lib/panel-slot/form-contribution.js +253 -0
  77. package/dist/lib/panel-slot/form-contribution.js.map +1 -0
  78. package/dist/lib/panel-slot/form-contributions.component.d.ts +27 -0
  79. package/dist/lib/panel-slot/form-contributions.component.d.ts.map +1 -0
  80. package/dist/lib/panel-slot/form-contributions.component.js +83 -0
  81. package/dist/lib/panel-slot/form-contributions.component.js.map +1 -0
  82. package/dist/lib/panel-slot/form-panel-slot.component.d.ts +2 -0
  83. package/dist/lib/panel-slot/form-panel-slot.component.d.ts.map +1 -1
  84. package/dist/lib/panel-slot/form-panel-slot.component.js +35 -4
  85. package/dist/lib/panel-slot/form-panel-slot.component.js.map +1 -1
  86. package/dist/lib/panel-slot/related-entity-grid-panel.component.d.ts +22 -0
  87. package/dist/lib/panel-slot/related-entity-grid-panel.component.d.ts.map +1 -0
  88. package/dist/lib/panel-slot/related-entity-grid-panel.component.js +78 -0
  89. package/dist/lib/panel-slot/related-entity-grid-panel.component.js.map +1 -0
  90. package/dist/lib/related-grid-height.d.ts +20 -0
  91. package/dist/lib/related-grid-height.d.ts.map +1 -0
  92. package/dist/lib/related-grid-height.js +30 -0
  93. package/dist/lib/related-grid-height.js.map +1 -0
  94. package/dist/lib/section-manager/section-manager.component.d.ts +20 -1
  95. package/dist/lib/section-manager/section-manager.component.d.ts.map +1 -1
  96. package/dist/lib/section-manager/section-manager.component.js +204 -25
  97. package/dist/lib/section-manager/section-manager.component.js.map +1 -1
  98. package/dist/lib/toolbar/form-toolbar.component.d.ts +55 -4
  99. package/dist/lib/toolbar/form-toolbar.component.d.ts.map +1 -1
  100. package/dist/lib/toolbar/form-toolbar.component.js +734 -306
  101. package/dist/lib/toolbar/form-toolbar.component.js.map +1 -1
  102. package/dist/lib/types/form-events.d.ts +35 -0
  103. package/dist/lib/types/form-events.d.ts.map +1 -1
  104. package/dist/lib/types/form-events.js +45 -0
  105. package/dist/lib/types/form-events.js.map +1 -1
  106. package/dist/lib/types/form-toolbar-item.d.ts +145 -0
  107. package/dist/lib/types/form-toolbar-item.d.ts.map +1 -0
  108. package/dist/lib/types/form-toolbar-item.js +2 -0
  109. package/dist/lib/types/form-toolbar-item.js.map +1 -0
  110. package/dist/lib/types/form-types.d.ts +8 -0
  111. package/dist/lib/types/form-types.d.ts.map +1 -1
  112. package/dist/lib/types/form-types.js.map +1 -1
  113. package/dist/lib/types/toolbar-config.d.ts +7 -2
  114. package/dist/lib/types/toolbar-config.d.ts.map +1 -1
  115. package/dist/lib/types/toolbar-config.js +6 -0
  116. package/dist/lib/types/toolbar-config.js.map +1 -1
  117. package/dist/module.d.ts +17 -14
  118. package/dist/module.d.ts.map +1 -1
  119. package/dist/module.js +14 -0
  120. package/dist/module.js.map +1 -1
  121. package/dist/public-api.d.ts +13 -0
  122. package/dist/public-api.d.ts.map +1 -1
  123. package/dist/public-api.js +14 -0
  124. package/dist/public-api.js.map +1 -1
  125. package/package.json +19 -18
@@ -0,0 +1,24 @@
1
+ /** Default for a user who has never touched the rail on this entity. */
2
+ export declare const FORM_CHROME_RAIL_PINNED_DEFAULT = true;
3
+ export declare const FORM_CHROME_RAIL_WIDTH_DEFAULT = 200;
4
+ export declare const FORM_CHROME_RAIL_WIDTH_MIN = 160;
5
+ export declare const FORM_CHROME_RAIL_WIDTH_MAX = 360;
6
+ export declare const FORM_CHROME_RAIL_COLLAPSED_PX = 36;
7
+ /** UserInfoEngine key: `mj.formChrome.<entity>.railPinned`. */
8
+ export declare function FormChromeRailPinnedKey(entityName: string): string;
9
+ /**
10
+ * Left-nav `activeGroup` is stored per entity. Unsaved (new) records must
11
+ * neither restore nor write it — they should open on the first first-class
12
+ * group (Details) instead of the last related section from another record.
13
+ */
14
+ export declare function ShouldPersistChromeActiveGroup(isSaved: boolean | null | undefined): boolean;
15
+ /** UserInfoEngine key: `mj.formChrome.<entity>.railWidth`. */
16
+ export declare function FormChromeRailWidthKey(entityName: string): string;
17
+ /** Missing / unknown values stay pinned so existing forms do not jump. */
18
+ export declare function ParseRailPinnedSetting(raw: string | undefined | null): boolean;
19
+ export declare function SerializeRailPinnedSetting(pinned: boolean): '1' | '0';
20
+ export declare function ClampRailWidth(px: number): number;
21
+ /** Missing / junk values fall back to the default expanded width. */
22
+ export declare function ParseRailWidthSetting(raw: string | undefined | null): number;
23
+ export declare function SerializeRailWidthSetting(px: number): string;
24
+ //# sourceMappingURL=form-chrome-rail-pref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-chrome-rail-pref.d.ts","sourceRoot":"","sources":["../../../src/lib/chrome/form-chrome-rail-pref.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,+DAA+D;AAC/D,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3F;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAQ9E;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,GAAG,GAAG,GAAG,CAErE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,qEAAqE;AACrE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAG5E;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,52 @@
1
+ /** Default for a user who has never touched the rail on this entity. */
2
+ export const FORM_CHROME_RAIL_PINNED_DEFAULT = true;
3
+ export const FORM_CHROME_RAIL_WIDTH_DEFAULT = 200;
4
+ export const FORM_CHROME_RAIL_WIDTH_MIN = 160;
5
+ export const FORM_CHROME_RAIL_WIDTH_MAX = 360;
6
+ export const FORM_CHROME_RAIL_COLLAPSED_PX = 36;
7
+ /** UserInfoEngine key: `mj.formChrome.<entity>.railPinned`. */
8
+ export function FormChromeRailPinnedKey(entityName) {
9
+ const name = (entityName ?? 'entity').trim().toLowerCase();
10
+ return `mj.formChrome.${name}.railPinned`;
11
+ }
12
+ /**
13
+ * Left-nav `activeGroup` is stored per entity. Unsaved (new) records must
14
+ * neither restore nor write it — they should open on the first first-class
15
+ * group (Details) instead of the last related section from another record.
16
+ */
17
+ export function ShouldPersistChromeActiveGroup(isSaved) {
18
+ return isSaved === true;
19
+ }
20
+ /** UserInfoEngine key: `mj.formChrome.<entity>.railWidth`. */
21
+ export function FormChromeRailWidthKey(entityName) {
22
+ const name = (entityName ?? 'entity').trim().toLowerCase();
23
+ return `mj.formChrome.${name}.railWidth`;
24
+ }
25
+ /** Missing / unknown values stay pinned so existing forms do not jump. */
26
+ export function ParseRailPinnedSetting(raw) {
27
+ if (raw === '0' || raw === 'false') {
28
+ return false;
29
+ }
30
+ if (raw === '1' || raw === 'true') {
31
+ return true;
32
+ }
33
+ return FORM_CHROME_RAIL_PINNED_DEFAULT;
34
+ }
35
+ export function SerializeRailPinnedSetting(pinned) {
36
+ return pinned ? '1' : '0';
37
+ }
38
+ export function ClampRailWidth(px) {
39
+ if (!Number.isFinite(px))
40
+ return FORM_CHROME_RAIL_WIDTH_DEFAULT;
41
+ return Math.min(FORM_CHROME_RAIL_WIDTH_MAX, Math.max(FORM_CHROME_RAIL_WIDTH_MIN, Math.round(px)));
42
+ }
43
+ /** Missing / junk values fall back to the default expanded width. */
44
+ export function ParseRailWidthSetting(raw) {
45
+ if (raw == null || raw.trim() === '')
46
+ return FORM_CHROME_RAIL_WIDTH_DEFAULT;
47
+ return ClampRailWidth(Number(raw));
48
+ }
49
+ export function SerializeRailWidthSetting(px) {
50
+ return String(ClampRailWidth(px));
51
+ }
52
+ //# sourceMappingURL=form-chrome-rail-pref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-chrome-rail-pref.js","sourceRoot":"","sources":["../../../src/lib/chrome/form-chrome-rail-pref.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,+BAA+B,GAAG,IAAI,CAAC;AAEpD,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAClD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,+DAA+D;AAC/D,MAAM,UAAU,uBAAuB,CAAC,UAAkB;IACtD,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3D,OAAO,iBAAiB,IAAI,aAAa,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,OAAmC;IAC9E,OAAO,OAAO,KAAK,IAAI,CAAC;AAC5B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACrD,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3D,OAAO,iBAAiB,IAAI,YAAY,CAAC;AAC7C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,sBAAsB,CAAC,GAA8B;IACjE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,+BAA+B,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACtD,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,8BAA8B,CAAC;IAChE,OAAO,IAAI,CAAC,GAAG,CACX,0BAA0B,EAC1B,IAAI,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CACvD,CAAC;AACN,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CAAC,GAA8B;IAChE,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,8BAA8B,CAAC;IAC5E,OAAO,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,EAAU;IAChD,OAAO,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC","sourcesContent":["/** Default for a user who has never touched the rail on this entity. */\nexport const FORM_CHROME_RAIL_PINNED_DEFAULT = true;\n\nexport const FORM_CHROME_RAIL_WIDTH_DEFAULT = 200;\nexport const FORM_CHROME_RAIL_WIDTH_MIN = 160;\nexport const FORM_CHROME_RAIL_WIDTH_MAX = 360;\nexport const FORM_CHROME_RAIL_COLLAPSED_PX = 36;\n\n/** UserInfoEngine key: `mj.formChrome.<entity>.railPinned`. */\nexport function FormChromeRailPinnedKey(entityName: string): string {\n const name = (entityName ?? 'entity').trim().toLowerCase();\n return `mj.formChrome.${name}.railPinned`;\n}\n\n/**\n * Left-nav `activeGroup` is stored per entity. Unsaved (new) records must\n * neither restore nor write it — they should open on the first first-class\n * group (Details) instead of the last related section from another record.\n */\nexport function ShouldPersistChromeActiveGroup(isSaved: boolean | null | undefined): boolean {\n return isSaved === true;\n}\n\n/** UserInfoEngine key: `mj.formChrome.<entity>.railWidth`. */\nexport function FormChromeRailWidthKey(entityName: string): string {\n const name = (entityName ?? 'entity').trim().toLowerCase();\n return `mj.formChrome.${name}.railWidth`;\n}\n\n/** Missing / unknown values stay pinned so existing forms do not jump. */\nexport function ParseRailPinnedSetting(raw: string | undefined | null): boolean {\n if (raw === '0' || raw === 'false') {\n return false;\n }\n if (raw === '1' || raw === 'true') {\n return true;\n }\n return FORM_CHROME_RAIL_PINNED_DEFAULT;\n}\n\nexport function SerializeRailPinnedSetting(pinned: boolean): '1' | '0' {\n return pinned ? '1' : '0';\n}\n\nexport function ClampRailWidth(px: number): number {\n if (!Number.isFinite(px)) return FORM_CHROME_RAIL_WIDTH_DEFAULT;\n return Math.min(\n FORM_CHROME_RAIL_WIDTH_MAX,\n Math.max(FORM_CHROME_RAIL_WIDTH_MIN, Math.round(px)),\n );\n}\n\n/** Missing / junk values fall back to the default expanded width. */\nexport function ParseRailWidthSetting(raw: string | undefined | null): number {\n if (raw == null || raw.trim() === '') return FORM_CHROME_RAIL_WIDTH_DEFAULT;\n return ClampRailWidth(Number(raw));\n}\n\nexport function SerializeRailWidthSetting(px: number): string {\n return String(ClampRailWidth(px));\n}\n"]}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Form chrome — how the container arranges sections (accordion vs left-nav,
3
+ * first-class vs More). Complements form contributions (what is on the form).
4
+ *
5
+ * @see plans/form-chrome-policy.md
6
+ */
7
+ import type { FormRole } from '@memberjunction/core';
8
+ export declare const MORE_SECTION_KEY = "__mj_form_more";
9
+ /** Field panels (default / inherited) collapse into this one left-nav item. */
10
+ export declare const DETAILS_SECTION_KEY = "__mj_form_details";
11
+ export declare const SYSTEM_METADATA_SECTION_KEY = "systemMetadata";
12
+ /**
13
+ * Expand-all / collapse-all only apply to stacked accordion panels.
14
+ * Left-nav and right-nav show one section at a time, so those buttons
15
+ * would be noise.
16
+ */
17
+ export declare function IsAccordionFormChrome(layout: string | null | undefined): boolean;
18
+ /** Audit / timestamp leftover sections always fold into More. */
19
+ export declare function IsAlwaysMoreSection(sectionKey: string, sectionName?: string): boolean;
20
+ /**
21
+ * Drop a schema entity-name prefix (`MJ_BizApps_Common: Contact Methods` →
22
+ * `Contact Methods`). DisplayName is the long-term source of truth; this keeps
23
+ * already-baked SectionName strings readable until CodeGen reruns.
24
+ */
25
+ export declare function HumanizeEntityTitle(name: string): string;
26
+ export interface FormChromeGroup {
27
+ Key: string;
28
+ Title: string;
29
+ Icon: string;
30
+ SectionKeys: string[];
31
+ /** True when this group is the More bucket (Detail related grids). */
32
+ IsMore: boolean;
33
+ /**
34
+ * Primary contribution that owns its own rail item and sorts in the
35
+ * lead band (before Details). Overview is the usual case.
36
+ */
37
+ IsLead?: boolean;
38
+ }
39
+ export interface FormChromeSpec {
40
+ Layout: 'accordion' | 'left-nav';
41
+ Groups: FormChromeGroup[];
42
+ /** SectionKey → role for related-entity panels. Field panels are omitted. */
43
+ RelatedRoles: ReadonlyMap<string, FormRole>;
44
+ MoreSectionKeys: string[];
45
+ /**
46
+ * L3 admin Title overlays, keyed by section key or contribution key.
47
+ * First-class group titles are already rewritten; More items and
48
+ * accordion headers read this map so the same override reaches both.
49
+ */
50
+ TitleBySectionKey?: ReadonlyMap<string, string>;
51
+ }
52
+ export interface FormChromePanelSnapshot {
53
+ SectionKey: string;
54
+ SectionName: string;
55
+ Variant: string;
56
+ Icon?: string;
57
+ }
58
+ export declare const DEFAULT_FORM_CHROME_SPEC: FormChromeSpec;
59
+ //# sourceMappingURL=form-chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-chrome.d.ts","sourceRoot":"","sources":["../../../src/lib/chrome/form-chrome.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,mBAAmB,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEhF;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAKrF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,sEAAsE;IACtE,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,WAAW,GAAG,UAAU,CAAC;IACjC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,wBAAwB,EAAE,cAKtC,CAAC"}
@@ -0,0 +1,37 @@
1
+ export const MORE_SECTION_KEY = '__mj_form_more';
2
+ /** Field panels (default / inherited) collapse into this one left-nav item. */
3
+ export const DETAILS_SECTION_KEY = '__mj_form_details';
4
+ export const SYSTEM_METADATA_SECTION_KEY = 'systemMetadata';
5
+ /**
6
+ * Expand-all / collapse-all only apply to stacked accordion panels.
7
+ * Left-nav and right-nav show one section at a time, so those buttons
8
+ * would be noise.
9
+ */
10
+ export function IsAccordionFormChrome(layout) {
11
+ return (layout ?? 'accordion') === 'accordion';
12
+ }
13
+ /** Audit / timestamp leftover sections always fold into More. */
14
+ export function IsAlwaysMoreSection(sectionKey, sectionName) {
15
+ const key = (sectionKey ?? '').trim().toLowerCase();
16
+ if (key === SYSTEM_METADATA_SECTION_KEY.toLowerCase())
17
+ return true;
18
+ const name = (sectionName ?? '').trim().toLowerCase();
19
+ return name === 'system metadata';
20
+ }
21
+ /**
22
+ * Drop a schema entity-name prefix (`MJ_BizApps_Common: Contact Methods` →
23
+ * `Contact Methods`). DisplayName is the long-term source of truth; this keeps
24
+ * already-baked SectionName strings readable until CodeGen reruns.
25
+ */
26
+ export function HumanizeEntityTitle(name) {
27
+ const trimmed = (name ?? '').trim();
28
+ const match = trimmed.match(/^[A-Za-z][A-Za-z0-9_]*:\s+(.+)$/);
29
+ return match?.[1]?.trim() || trimmed;
30
+ }
31
+ export const DEFAULT_FORM_CHROME_SPEC = {
32
+ Layout: 'accordion',
33
+ Groups: [],
34
+ RelatedRoles: new Map(),
35
+ MoreSectionKeys: [],
36
+ };
37
+ //# sourceMappingURL=form-chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-chrome.js","sourceRoot":"","sources":["../../../src/lib/chrome/form-chrome.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEvD,MAAM,CAAC,MAAM,2BAA2B,GAAG,gBAAgB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAiC;IACnE,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,KAAK,WAAW,CAAC;AACnD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,WAAoB;IACxE,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpD,IAAI,GAAG,KAAK,2BAA2B,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtD,OAAO,IAAI,KAAK,iBAAiB,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC/D,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC;AACzC,CAAC;AAqCD,MAAM,CAAC,MAAM,wBAAwB,GAAmB;IACpD,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,IAAI,GAAG,EAAE;IACvB,eAAe,EAAE,EAAE;CACtB,CAAC","sourcesContent":["/**\n * Form chrome — how the container arranges sections (accordion vs left-nav,\n * first-class vs More). Complements form contributions (what is on the form).\n *\n * @see plans/form-chrome-policy.md\n */\nimport type { FormRole } from '@memberjunction/core';\n\nexport const MORE_SECTION_KEY = '__mj_form_more';\n\n/** Field panels (default / inherited) collapse into this one left-nav item. */\nexport const DETAILS_SECTION_KEY = '__mj_form_details';\n\nexport const SYSTEM_METADATA_SECTION_KEY = 'systemMetadata';\n\n/**\n * Expand-all / collapse-all only apply to stacked accordion panels.\n * Left-nav and right-nav show one section at a time, so those buttons\n * would be noise.\n */\nexport function IsAccordionFormChrome(layout: string | null | undefined): boolean {\n return (layout ?? 'accordion') === 'accordion';\n}\n\n/** Audit / timestamp leftover sections always fold into More. */\nexport function IsAlwaysMoreSection(sectionKey: string, sectionName?: string): boolean {\n const key = (sectionKey ?? '').trim().toLowerCase();\n if (key === SYSTEM_METADATA_SECTION_KEY.toLowerCase()) return true;\n const name = (sectionName ?? '').trim().toLowerCase();\n return name === 'system metadata';\n}\n\n/**\n * Drop a schema entity-name prefix (`MJ_BizApps_Common: Contact Methods` →\n * `Contact Methods`). DisplayName is the long-term source of truth; this keeps\n * already-baked SectionName strings readable until CodeGen reruns.\n */\nexport function HumanizeEntityTitle(name: string): string {\n const trimmed = (name ?? '').trim();\n const match = trimmed.match(/^[A-Za-z][A-Za-z0-9_]*:\\s+(.+)$/);\n return match?.[1]?.trim() || trimmed;\n}\n\nexport interface FormChromeGroup {\n Key: string;\n Title: string;\n Icon: string;\n SectionKeys: string[];\n /** True when this group is the More bucket (Detail related grids). */\n IsMore: boolean;\n /**\n * Primary contribution that owns its own rail item and sorts in the\n * lead band (before Details). Overview is the usual case.\n */\n IsLead?: boolean;\n}\n\nexport interface FormChromeSpec {\n Layout: 'accordion' | 'left-nav';\n Groups: FormChromeGroup[];\n /** SectionKey → role for related-entity panels. Field panels are omitted. */\n RelatedRoles: ReadonlyMap<string, FormRole>;\n MoreSectionKeys: string[];\n /**\n * L3 admin Title overlays, keyed by section key or contribution key.\n * First-class group titles are already rewritten; More items and\n * accordion headers read this map so the same override reaches both.\n */\n TitleBySectionKey?: ReadonlyMap<string, string>;\n}\n\nexport interface FormChromePanelSnapshot {\n SectionKey: string;\n SectionName: string;\n Variant: string;\n Icon?: string;\n}\n\nexport const DEFAULT_FORM_CHROME_SPEC: FormChromeSpec = {\n Layout: 'accordion',\n Groups: [],\n RelatedRoles: new Map(),\n MoreSectionKeys: [],\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import { type FormChromeRule, type IMetadataProvider } from '@memberjunction/core';
2
+ export declare const FORM_CHROME_RULES_ENTITY = "MJ: Form Chrome Rules";
3
+ /**
4
+ * Load L3 install overlay rows for one parent form entity.
5
+ * Returns [] when the entity is not in metadata (migration / CodeGen not applied).
6
+ */
7
+ export declare function LoadFormChromeRules(parentEntityId: string, provider?: IMetadataProvider): Promise<FormChromeRule[]>;
8
+ //# sourceMappingURL=load-form-chrome-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-form-chrome-rules.d.ts","sourceRoot":"","sources":["../../../src/lib/chrome/load-form-chrome-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,cAAc,EAEnB,KAAK,iBAAiB,EACzB,MAAM,sBAAsB,CAAC;AAG9B,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAahE;;;GAGG;AACH,wBAAsB,mBAAmB,CACrC,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,cAAc,EAAE,CAAC,CAkC3B"}
@@ -0,0 +1,70 @@
1
+ import { Metadata, RunView, } from '@memberjunction/core';
2
+ import { SafeJSONParse } from '@memberjunction/global';
3
+ export const FORM_CHROME_RULES_ENTITY = 'MJ: Form Chrome Rules';
4
+ /**
5
+ * Load L3 install overlay rows for one parent form entity.
6
+ * Returns [] when the entity is not in metadata (migration / CodeGen not applied).
7
+ */
8
+ export async function LoadFormChromeRules(parentEntityId, provider) {
9
+ const id = parentEntityId.trim();
10
+ if (!isEntityId(id))
11
+ return [];
12
+ const md = provider ?? Metadata.Provider;
13
+ const rulesEntity = md?.EntityByName(FORM_CHROME_RULES_ENTITY);
14
+ if (!rulesEntity)
15
+ return [];
16
+ // Read through the SAME provider the check above resolved. `new RunView()` binds the GLOBAL
17
+ // provider, so in a multi-provider app this validated the entity against the caller's provider
18
+ // and then read the rows from a different one — yielding another environment's chrome rules, or
19
+ // none at all, depending on which provider happened to be global at the time.
20
+ const rv = RunView.FromMetadataProvider(md);
21
+ const fields = [
22
+ 'EntityID',
23
+ 'TargetKind',
24
+ 'RelatedEntityID',
25
+ 'ContributionKey',
26
+ 'Inclusion',
27
+ 'JoinFields',
28
+ 'Sequence',
29
+ ];
30
+ // Title is additive — skip it until migrate + CodeGen have published the column.
31
+ if (rulesEntity.Fields.some((field) => field.Name === 'Title')) {
32
+ fields.push('Title');
33
+ }
34
+ const result = await rv.RunView({
35
+ EntityName: FORM_CHROME_RULES_ENTITY,
36
+ ExtraFilter: `EntityID='${id}'`,
37
+ Fields: fields,
38
+ OrderBy: 'Sequence ASC',
39
+ ResultType: 'simple',
40
+ });
41
+ if (!result.Success)
42
+ return [];
43
+ return (result.Results ?? []).map(toRule);
44
+ }
45
+ function toRule(row) {
46
+ const title = row.Title?.trim();
47
+ return {
48
+ EntityID: row.EntityID,
49
+ TargetKind: row.TargetKind,
50
+ RelatedEntityID: row.RelatedEntityID,
51
+ ContributionKey: row.ContributionKey,
52
+ Inclusion: row.Inclusion,
53
+ JoinFields: parseJoinFields(row.JoinFields),
54
+ Sequence: row.Sequence,
55
+ Title: title && title.length > 0 ? title : null,
56
+ };
57
+ }
58
+ function parseJoinFields(raw) {
59
+ if (raw == null || raw.trim().length === 0)
60
+ return null;
61
+ const parsed = SafeJSONParse(raw, false);
62
+ if (!Array.isArray(parsed))
63
+ return null;
64
+ const fields = parsed.map((f) => (typeof f === 'string' ? f.trim() : '')).filter((f) => f.length > 0);
65
+ return fields.length > 0 ? fields : null;
66
+ }
67
+ function isEntityId(value) {
68
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
69
+ }
70
+ //# sourceMappingURL=load-form-chrome-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-form-chrome-rules.js","sourceRoot":"","sources":["../../../src/lib/chrome/load-form-chrome-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Metadata,\n RunView,\n type FormChromeRule,\n type FormInclusion,\n type IMetadataProvider,\n} from '@memberjunction/core';\nimport { SafeJSONParse } from '@memberjunction/global';\n\nexport const FORM_CHROME_RULES_ENTITY = 'MJ: Form Chrome Rules';\n\ninterface FormChromeRuleRow {\n EntityID: string;\n TargetKind: FormChromeRule['TargetKind'];\n RelatedEntityID: string | null;\n ContributionKey: string | null;\n Inclusion: FormInclusion;\n JoinFields: string | null;\n Sequence: number | null;\n Title?: string | null;\n}\n\n/**\n * Load L3 install overlay rows for one parent form entity.\n * Returns [] when the entity is not in metadata (migration / CodeGen not applied).\n */\nexport async function LoadFormChromeRules(\n parentEntityId: string,\n provider?: IMetadataProvider,\n): Promise<FormChromeRule[]> {\n const id = parentEntityId.trim();\n if (!isEntityId(id)) return [];\n const md = provider ?? Metadata.Provider;\n const rulesEntity = md?.EntityByName(FORM_CHROME_RULES_ENTITY);\n if (!rulesEntity) return [];\n\n // Read through the SAME provider the check above resolved. `new RunView()` binds the GLOBAL\n // provider, so in a multi-provider app this validated the entity against the caller's provider\n // and then read the rows from a different one — yielding another environment's chrome rules, or\n // none at all, depending on which provider happened to be global at the time.\n const rv = RunView.FromMetadataProvider(md);\n const fields = [\n 'EntityID',\n 'TargetKind',\n 'RelatedEntityID',\n 'ContributionKey',\n 'Inclusion',\n 'JoinFields',\n 'Sequence',\n ];\n // Title is additive — skip it until migrate + CodeGen have published the column.\n if (rulesEntity.Fields.some((field) => field.Name === 'Title')) {\n fields.push('Title');\n }\n const result = await rv.RunView<FormChromeRuleRow>({\n EntityName: FORM_CHROME_RULES_ENTITY,\n ExtraFilter: `EntityID='${id}'`,\n Fields: fields,\n OrderBy: 'Sequence ASC',\n ResultType: 'simple',\n });\n if (!result.Success) return [];\n return (result.Results ?? []).map(toRule);\n}\n\nfunction toRule(row: FormChromeRuleRow): FormChromeRule {\n const title = row.Title?.trim();\n return {\n EntityID: row.EntityID,\n TargetKind: row.TargetKind,\n RelatedEntityID: row.RelatedEntityID,\n ContributionKey: row.ContributionKey,\n Inclusion: row.Inclusion,\n JoinFields: parseJoinFields(row.JoinFields),\n Sequence: row.Sequence,\n Title: title && title.length > 0 ? title : null,\n };\n}\n\nfunction parseJoinFields(raw: string | null): string[] | null {\n if (raw == null || raw.trim().length === 0) return null;\n const parsed = SafeJSONParse<string[]>(raw, false);\n if (!Array.isArray(parsed)) return null;\n const fields = parsed.map((f) => (typeof f === 'string' ? f.trim() : '')).filter((f) => f.length > 0);\n return fields.length > 0 ? fields : null;\n}\n\nfunction isEntityId(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n"]}
@@ -0,0 +1,114 @@
1
+ import { EntityInfo, type FormChromeRule, type FormInclusion, type FormRole, type IEntityFormConfiguration, type RelatedFormRoleCandidate, type RelatedFormRoleResolution } from '@memberjunction/core';
2
+ import { BaseFormPolicy } from './base-form-policy';
3
+ import { type FormChromeGroup, type FormChromePanelSnapshot, type FormChromeSpec } from './form-chrome';
4
+ /** User override of which sections live in More vs first-class. */
5
+ export interface ChromeMembershipOverride {
6
+ moreSectionKeys?: readonly string[];
7
+ firstClassSectionKeys?: readonly string[];
8
+ }
9
+ export interface ResolveFormChromeInput {
10
+ Entity: EntityInfo;
11
+ Panels: FormChromePanelSnapshot[];
12
+ /** Related-entity schema by entity ID. Built from the active provider. */
13
+ RelatedSchemaByEntityId: ReadonlyMap<string, string>;
14
+ /**
15
+ * Section keys a contribution claimed or replaced. Must not appear in
16
+ * the rail — otherwise a custom Contact Methods widget and the baked
17
+ * grid merge into one group and both show.
18
+ */
19
+ HiddenSectionKeys?: readonly string[];
20
+ /** Persisted user move-in / move-out of More. */
21
+ Membership?: ChromeMembershipOverride | null;
22
+ /**
23
+ * RelatedEntityID (lowercase) → how many EntityRelationships point at
24
+ * that entity. Used as graph in-degree by the smart ranker.
25
+ */
26
+ InboundRelationshipCountByEntityId?: ReadonlyMap<string, number>;
27
+ /**
28
+ * Section keys of registered form contributions (custom widgets). These
29
+ * stay first-class instead of folding into Details, and rank above
30
+ * stock related grids.
31
+ */
32
+ ContributionSectionKeys?: readonly string[];
33
+ /** contribution SectionKey → details | more. Overrides first-class lift. */
34
+ ContributionChromeGroupByKey?: ReadonlyMap<string, 'details' | 'more'>;
35
+ /**
36
+ * L1 inclusion from the winning contribution registration.
37
+ * L3 `ChromeRules` still wins on the same key.
38
+ */
39
+ ContributionInclusionByKey?: ReadonlyMap<string, FormInclusion>;
40
+ /** `sortKey` from the winning registration. Higher = earlier in the lead band. */
41
+ ContributionSortKeyByKey?: ReadonlyMap<string, number>;
42
+ /**
43
+ * Install overlay (L3) from `MJ: Form Chrome Rules`. Empty when the
44
+ * entity is not installed or the parent has no rows.
45
+ */
46
+ ChromeRules?: readonly FormChromeRule[];
47
+ /**
48
+ * When false, do not invent chrome groups for DisplayInForm related
49
+ * that have no baked / contributed panel. Custom forms that set
50
+ * `ShowRelatedEntities: false` use this so leftover More does not
51
+ * appear for grids the template already owns (or chose not to show).
52
+ */
53
+ IncludeUnbakedRelated?: boolean;
54
+ }
55
+ export interface ResolveFormChromeResult {
56
+ Spec: FormChromeSpec;
57
+ RelatedRoles: RelatedFormRoleResolution;
58
+ PolicyUsed: boolean;
59
+ }
60
+ /**
61
+ * Last-wins `BaseFormPolicy` for this entity, or `null` when none is registered.
62
+ */
63
+ export declare function ResolveFormPolicy(entityName: string): BaseFormPolicy | null;
64
+ export declare function BuildRelatedFormRoleCandidates(entity: EntityInfo, relatedSchemaByEntityId: ReadonlyMap<string, string>, inboundCountByRelatedEntityId?: ReadonlyMap<string, number>): RelatedFormRoleCandidate[];
65
+ export declare function ResolveFormChrome(input: ResolveFormChromeInput): ResolveFormChromeResult;
66
+ /**
67
+ * Policy may rename groups and swap icons. Membership (section keys and
68
+ * More vs first-class) is data — a violating decorate is ignored.
69
+ */
70
+ export declare function TakeDecoratedChrome(base: FormChromeSpec, decorated: FormChromeSpec): FormChromeSpec;
71
+ /**
72
+ * L3 Title overlay. Last Sequence wins. Blank Title is ignored so an
73
+ * incomplete rule cannot wipe DisplayName. Applied after policy decorate
74
+ * so an admin title survives an OpenApp policy rename.
75
+ */
76
+ export declare function ApplyFormChromeRuleTitles(spec: FormChromeSpec, entity: EntityInfo, rules: readonly FormChromeRule[]): void;
77
+ export declare function BuildDefaultChromeSpec(panels: FormChromePanelSnapshot[], relatedRoles: ReadonlyMap<string, FormRole>, formConfig: IEntityFormConfiguration | null, contributionSectionKeys?: readonly string[], contributionChromeGroupByKey?: ReadonlyMap<string, 'details' | 'more'>): FormChromeSpec;
78
+ /** First SectionKey index in a user order; used to sort rail groups. */
79
+ export declare function ChromeGroupOrderIndex(group: FormChromeGroup, sectionOrder: readonly string[]): number;
80
+ /**
81
+ * Layer a (possibly incomplete) user ranking on the current default rail.
82
+ * Keys the user ranked keep that relative order. Keys they never ranked
83
+ * (Overview, a new related grid) stay in their default slots instead of
84
+ * falling to the end — `form.sections` does not list slot-mounted leads.
85
+ */
86
+ export declare function OverlayChromeSectionOrder(defaultOrder: readonly string[], userOrder: readonly string[]): string[];
87
+ /** Reorder More children from a persisted section-key order. */
88
+ export declare function OrderMoreSectionKeys(moreKeys: readonly string[], sectionOrder: readonly string[]): string[];
89
+ /**
90
+ * Keep the first-class rail order from the previous spec when chrome
91
+ * re-resolves (slot mount, grid load, contribution key appearing).
92
+ * Clicking a rail item must not reshuffle the list.
93
+ * New related groups append. New lead contributions (Overview) insert
94
+ * into the lead band before Details. More stays last.
95
+ * User drag still wins via {@link OrderChromeGroups}.
96
+ */
97
+ export declare function StabilizeFirstClassGroupOrder(previous: FormChromeSpec | null | undefined, next: FormChromeSpec): FormChromeSpec;
98
+ /** Reorder first-class rail groups from a persisted section-key order. More stays last. */
99
+ export declare function OrderChromeGroups(groups: readonly FormChromeGroup[], sectionOrder: readonly string[]): FormChromeGroup[];
100
+ /**
101
+ * Move every SectionKey of `dragged` as a block in front of `target`
102
+ * inside a section-order list. Used by left-nav rail drag/drop.
103
+ */
104
+ export declare function MoveChromeGroupInSectionOrder(sectionOrder: readonly string[], dragged: FormChromeGroup, target: FormChromeGroup): string[];
105
+ /** Collapse rail items that share a humanized title (From/To Relationships). */
106
+ export declare function MergeChromeGroupsByTitle(groups: FormChromeGroup[]): FormChromeGroup[];
107
+ /**
108
+ * Apply a persisted user membership (move in/out of More) onto a spec
109
+ * in place. Always-more sections (System Metadata) cannot leave More.
110
+ */
111
+ export declare function ApplyUserChromeMembership(spec: FormChromeSpec, override: ChromeMembershipOverride | null | undefined, panels?: readonly FormChromePanelSnapshot[]): FormChromeSpec;
112
+ /** Rebuild Groups / MoreSectionKeys after membership changes. Layout is unchanged. */
113
+ export declare function RebuildChromeSpecMembership(spec: FormChromeSpec, moreKeys: readonly string[], panels?: readonly FormChromePanelSnapshot[]): FormChromeSpec;
114
+ //# sourceMappingURL=resolve-form-chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-form-chrome.d.ts","sourceRoot":"","sources":["../../../src/lib/chrome/resolve-form-chrome.ts"],"names":[],"mappings":"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"}