@aglyn/shared-ui-jsx 1.0.0-beta.143

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 (261) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +63 -0
  4. package/src/index.d.ts +48 -0
  5. package/src/index.js +179 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/aglyn-text.d.ts +86 -0
  8. package/src/lib/components/aglyn-text.js +44 -0
  9. package/src/lib/components/aglyn-text.js.map +1 -0
  10. package/src/lib/components/app-link.d.ts +74 -0
  11. package/src/lib/components/app-link.js +139 -0
  12. package/src/lib/components/app-link.js.map +1 -0
  13. package/src/lib/components/aspect-ratio.d.ts +59 -0
  14. package/src/lib/components/aspect-ratio.js +153 -0
  15. package/src/lib/components/aspect-ratio.js.map +1 -0
  16. package/src/lib/components/background-image.component.d.ts +30 -0
  17. package/src/lib/components/background-image.component.js +42 -0
  18. package/src/lib/components/background-image.component.js.map +1 -0
  19. package/src/lib/components/card-columns.d.ts +86 -0
  20. package/src/lib/components/card-columns.js +148 -0
  21. package/src/lib/components/card-columns.js.map +1 -0
  22. package/src/lib/components/card-display.d.ts +36 -0
  23. package/src/lib/components/card-display.js +158 -0
  24. package/src/lib/components/card-display.js.map +1 -0
  25. package/src/lib/components/card-list-item.d.ts +35 -0
  26. package/src/lib/components/card-list-item.js +137 -0
  27. package/src/lib/components/card-list-item.js.map +1 -0
  28. package/src/lib/components/children-function-prop.d.ts +25 -0
  29. package/src/lib/components/children-function-prop.js +29 -0
  30. package/src/lib/components/children-function-prop.js.map +1 -0
  31. package/src/lib/components/confirmation-provider.component.d.ts +19 -0
  32. package/src/lib/components/confirmation-provider.component.js +83 -0
  33. package/src/lib/components/confirmation-provider.component.js.map +1 -0
  34. package/src/lib/components/container.d.ts +25 -0
  35. package/src/lib/components/container.js +62 -0
  36. package/src/lib/components/container.js.map +1 -0
  37. package/src/lib/components/data-table.component.d.ts +54 -0
  38. package/src/lib/components/data-table.component.js +211 -0
  39. package/src/lib/components/data-table.component.js.map +1 -0
  40. package/src/lib/components/dialog-confirm.d.ts +36 -0
  41. package/src/lib/components/dialog-confirm.js +74 -0
  42. package/src/lib/components/dialog-confirm.js.map +1 -0
  43. package/src/lib/components/ellipsis-pulse.component.d.ts +22 -0
  44. package/src/lib/components/ellipsis-pulse.component.js +51 -0
  45. package/src/lib/components/ellipsis-pulse.component.js.map +1 -0
  46. package/src/lib/components/emotion-cache-provider.d.ts +31 -0
  47. package/src/lib/components/emotion-cache-provider.js +40 -0
  48. package/src/lib/components/emotion-cache-provider.js.map +1 -0
  49. package/src/lib/components/empty-state.component.d.ts +63 -0
  50. package/src/lib/components/empty-state.component.js +214 -0
  51. package/src/lib/components/empty-state.component.js.map +1 -0
  52. package/src/lib/components/error-boundary.component.d.ts +28 -0
  53. package/src/lib/components/error-boundary.component.js +86 -0
  54. package/src/lib/components/error-boundary.component.js.map +1 -0
  55. package/src/lib/components/grid-buttons.d.ts +26 -0
  56. package/src/lib/components/grid-buttons.js +45 -0
  57. package/src/lib/components/grid-buttons.js.map +1 -0
  58. package/src/lib/components/grid-items.d.ts +103 -0
  59. package/src/lib/components/grid-items.js +336 -0
  60. package/src/lib/components/grid-items.js.map +1 -0
  61. package/src/lib/components/grid-list.d.ts +37 -0
  62. package/src/lib/components/grid-list.js +156 -0
  63. package/src/lib/components/grid-list.js.map +1 -0
  64. package/src/lib/components/help-tip.component.d.ts +30 -0
  65. package/src/lib/components/help-tip.component.js +139 -0
  66. package/src/lib/components/help-tip.component.js.map +1 -0
  67. package/src/lib/components/link-navigation-reporter.d.ts +24 -0
  68. package/src/lib/components/link-navigation-reporter.js +64 -0
  69. package/src/lib/components/link-navigation-reporter.js.map +1 -0
  70. package/src/lib/components/list-pagination.component.d.ts +57 -0
  71. package/src/lib/components/list-pagination.component.js +90 -0
  72. package/src/lib/components/list-pagination.component.js.map +1 -0
  73. package/src/lib/components/list-table.component.d.ts +155 -0
  74. package/src/lib/components/list-table.component.js +369 -0
  75. package/src/lib/components/list-table.component.js.map +1 -0
  76. package/src/lib/components/loading-layout-app.component.d.ts +35 -0
  77. package/src/lib/components/loading-layout-app.component.js +42 -0
  78. package/src/lib/components/loading-layout-app.component.js.map +1 -0
  79. package/src/lib/components/loading-modal-overlay.d.ts +30 -0
  80. package/src/lib/components/loading-modal-overlay.js +156 -0
  81. package/src/lib/components/loading-modal-overlay.js.map +1 -0
  82. package/src/lib/components/loading-modal.d.ts +19 -0
  83. package/src/lib/components/loading-modal.js +113 -0
  84. package/src/lib/components/loading-modal.js.map +1 -0
  85. package/src/lib/components/loading-text.component.d.ts +21 -0
  86. package/src/lib/components/loading-text.component.js +40 -0
  87. package/src/lib/components/loading-text.component.js.map +1 -0
  88. package/src/lib/components/mdi-icon/index.d.ts +2 -0
  89. package/src/lib/components/mdi-icon/index.js +4 -0
  90. package/src/lib/components/mdi-icon/index.js.map +1 -0
  91. package/src/lib/components/mdi-icon/md-icon-stack.d.ts +31 -0
  92. package/src/lib/components/mdi-icon/md-icon-stack.js +101 -0
  93. package/src/lib/components/mdi-icon/md-icon-stack.js.map +1 -0
  94. package/src/lib/components/mdi-icon/md-icon.d.ts +32 -0
  95. package/src/lib/components/mdi-icon/md-icon.js +147 -0
  96. package/src/lib/components/mdi-icon/md-icon.js.map +1 -0
  97. package/src/lib/components/mdi-icon/mdi-icon-from-id.d.ts +23 -0
  98. package/src/lib/components/mdi-icon/mdi-icon-from-id.js +35 -0
  99. package/src/lib/components/mdi-icon/mdi-icon-from-id.js.map +1 -0
  100. package/src/lib/components/mdi-icon/mdi-icon.d.ts +24 -0
  101. package/src/lib/components/mdi-icon/mdi-icon.js +46 -0
  102. package/src/lib/components/mdi-icon/mdi-icon.js.map +1 -0
  103. package/src/lib/components/measured-figures.component.d.ts +64 -0
  104. package/src/lib/components/measured-figures.component.js +161 -0
  105. package/src/lib/components/measured-figures.component.js.map +1 -0
  106. package/src/lib/components/menu.d.ts +45 -0
  107. package/src/lib/components/menu.js +229 -0
  108. package/src/lib/components/menu.js.map +1 -0
  109. package/src/lib/components/mui-shadow-dom.d.ts +38 -0
  110. package/src/lib/components/mui-shadow-dom.js +161 -0
  111. package/src/lib/components/mui-shadow-dom.js.map +1 -0
  112. package/src/lib/components/navigation-drawer.component.d.ts +31 -0
  113. package/src/lib/components/navigation-drawer.component.js +76 -0
  114. package/src/lib/components/navigation-drawer.component.js.map +1 -0
  115. package/src/lib/components/navigation-intent.d.ts +18 -0
  116. package/src/lib/components/navigation-intent.js +56 -0
  117. package/src/lib/components/navigation-intent.js.map +1 -0
  118. package/src/lib/components/navigation-view/index.d.ts +18 -0
  119. package/src/lib/components/navigation-view/index.js +19 -0
  120. package/src/lib/components/navigation-view/index.js.map +1 -0
  121. package/src/lib/components/navigation-view/navigation-view.d.ts +35 -0
  122. package/src/lib/components/navigation-view/navigation-view.js +175 -0
  123. package/src/lib/components/navigation-view/navigation-view.js.map +1 -0
  124. package/src/lib/components/next-link.d.ts +27 -0
  125. package/src/lib/components/next-link.js +88 -0
  126. package/src/lib/components/next-link.js.map +1 -0
  127. package/src/lib/components/popper-styled.component.d.ts +25 -0
  128. package/src/lib/components/popper-styled.component.js +129 -0
  129. package/src/lib/components/popper-styled.component.js.map +1 -0
  130. package/src/lib/components/quota-readout.component.d.ts +69 -0
  131. package/src/lib/components/quota-readout.component.js +52 -0
  132. package/src/lib/components/quota-readout.component.js.map +1 -0
  133. package/src/lib/components/resizeable-stack.d.ts +4 -0
  134. package/src/lib/components/resizeable-stack.js +23 -0
  135. package/src/lib/components/resizeable-stack.js.map +1 -0
  136. package/src/lib/components/row-actions-menu.component.d.ts +53 -0
  137. package/src/lib/components/row-actions-menu.component.js +132 -0
  138. package/src/lib/components/row-actions-menu.component.js.map +1 -0
  139. package/src/lib/components/ruler-guides.component.d.ts +35 -0
  140. package/src/lib/components/ruler-guides.component.js +166 -0
  141. package/src/lib/components/ruler-guides.component.js.map +1 -0
  142. package/src/lib/components/sandbox-frame.d.ts +42 -0
  143. package/src/lib/components/sandbox-frame.js +122 -0
  144. package/src/lib/components/sandbox-frame.js.map +1 -0
  145. package/src/lib/components/scroll-reaction.d.ts +59 -0
  146. package/src/lib/components/scroll-reaction.js +43 -0
  147. package/src/lib/components/scroll-reaction.js.map +1 -0
  148. package/src/lib/components/scroll-table.component.d.ts +124 -0
  149. package/src/lib/components/scroll-table.component.js +103 -0
  150. package/src/lib/components/scroll-table.component.js.map +1 -0
  151. package/src/lib/components/shadow-dom/index.d.ts +18 -0
  152. package/src/lib/components/shadow-dom/index.js +19 -0
  153. package/src/lib/components/shadow-dom/index.js.map +1 -0
  154. package/src/lib/components/shadow-dom/shadow-dom.d.ts +42 -0
  155. package/src/lib/components/shadow-dom/shadow-dom.js +123 -0
  156. package/src/lib/components/shadow-dom/shadow-dom.js.map +1 -0
  157. package/src/lib/components/splash-screen.d.ts +33 -0
  158. package/src/lib/components/splash-screen.js +105 -0
  159. package/src/lib/components/splash-screen.js.map +1 -0
  160. package/src/lib/components/sr-only.d.ts +20 -0
  161. package/src/lib/components/sr-only.js +25 -0
  162. package/src/lib/components/sr-only.js.map +1 -0
  163. package/src/lib/components/status-screen-plain.component.d.ts +27 -0
  164. package/src/lib/components/status-screen-plain.component.js +178 -0
  165. package/src/lib/components/status-screen-plain.component.js.map +1 -0
  166. package/src/lib/components/usage-meter.component.d.ts +30 -0
  167. package/src/lib/components/usage-meter.component.js +92 -0
  168. package/src/lib/components/usage-meter.component.js.map +1 -0
  169. package/src/lib/components/variable-text-field.component.d.ts +50 -0
  170. package/src/lib/components/variable-text-field.component.js +188 -0
  171. package/src/lib/components/variable-text-field.component.js.map +1 -0
  172. package/src/lib/components/zoomable-panning-component/index.d.ts +1 -0
  173. package/src/lib/components/zoomable-panning-component/index.js +3 -0
  174. package/src/lib/components/zoomable-panning-component/index.js.map +1 -0
  175. package/src/lib/components/zoomable-panning-component/util.d.ts +58 -0
  176. package/src/lib/components/zoomable-panning-component/util.js +114 -0
  177. package/src/lib/components/zoomable-panning-component/util.js.map +1 -0
  178. package/src/lib/components/zoomable-panning-component/zoomable-panning-component.d.ts +132 -0
  179. package/src/lib/components/zoomable-panning-component/zoomable-panning-component.js +728 -0
  180. package/src/lib/components/zoomable-panning-component/zoomable-panning-component.js.map +1 -0
  181. package/src/lib/const/aglyn-besigner-logo-full.d.ts +39 -0
  182. package/src/lib/const/aglyn-besigner-logo-full.js +146 -0
  183. package/src/lib/const/aglyn-besigner-logo-full.js.map +1 -0
  184. package/src/lib/const/aglyn-console-logo-full.d.ts +34 -0
  185. package/src/lib/const/aglyn-console-logo-full.js +142 -0
  186. package/src/lib/const/aglyn-console-logo-full.js.map +1 -0
  187. package/src/lib/const/aglyn-logo-class-keys.d.ts +30 -0
  188. package/src/lib/const/aglyn-logo-class-keys.js +32 -0
  189. package/src/lib/const/aglyn-logo-class-keys.js.map +1 -0
  190. package/src/lib/const/aglyn-logo-full.d.ts +29 -0
  191. package/src/lib/const/aglyn-logo-full.js +111 -0
  192. package/src/lib/const/aglyn-logo-full.js.map +1 -0
  193. package/src/lib/const/list-filter.d.ts +260 -0
  194. package/src/lib/const/list-filter.js +409 -0
  195. package/src/lib/const/list-filter.js.map +1 -0
  196. package/src/lib/const/prebuilt-components.d.ts +17 -0
  197. package/src/lib/const/prebuilt-components.js +22 -0
  198. package/src/lib/const/prebuilt-components.js.map +1 -0
  199. package/src/lib/const/svg-icons.d.ts +75 -0
  200. package/src/lib/const/svg-icons.js +313 -0
  201. package/src/lib/const/svg-icons.js.map +1 -0
  202. package/src/lib/const/table-pagination.d.ts +106 -0
  203. package/src/lib/const/table-pagination.js +106 -0
  204. package/src/lib/const/table-pagination.js.map +1 -0
  205. package/src/lib/contexts/confirmation.context.d.ts +996 -0
  206. package/src/lib/contexts/confirmation.context.js +49 -0
  207. package/src/lib/contexts/confirmation.context.js.map +1 -0
  208. package/src/lib/contexts/loading.context.d.ts +93 -0
  209. package/src/lib/contexts/loading.context.js +126 -0
  210. package/src/lib/contexts/loading.context.js.map +1 -0
  211. package/src/lib/hocs/create-hoc-with-context-consumer.d.ts +36 -0
  212. package/src/lib/hocs/create-hoc-with-context-consumer.js +44 -0
  213. package/src/lib/hocs/create-hoc-with-context-consumer.js.map +1 -0
  214. package/src/lib/hocs/with-hoc.d.ts +32 -0
  215. package/src/lib/hocs/with-hoc.js +37 -0
  216. package/src/lib/hocs/with-hoc.js.map +1 -0
  217. package/src/lib/hooks/mdi-icon/use-mdi-icon.d.ts +20 -0
  218. package/src/lib/hooks/mdi-icon/use-mdi-icon.js +48 -0
  219. package/src/lib/hooks/mdi-icon/use-mdi-icon.js.map +1 -0
  220. package/src/lib/hooks/mdi-icon/use-mdi-icons-fuzzy.d.ts +26 -0
  221. package/src/lib/hooks/mdi-icon/use-mdi-icons-fuzzy.js +73 -0
  222. package/src/lib/hooks/mdi-icon/use-mdi-icons-fuzzy.js.map +1 -0
  223. package/src/lib/hooks/mdi-icon/use-mdi-icons.d.ts +19 -0
  224. package/src/lib/hooks/mdi-icon/use-mdi-icons.js +49 -0
  225. package/src/lib/hooks/mdi-icon/use-mdi-icons.js.map +1 -0
  226. package/src/lib/hooks/router-events.d.ts +56 -0
  227. package/src/lib/hooks/router-events.js +88 -0
  228. package/src/lib/hooks/router-events.js.map +1 -0
  229. package/src/lib/hooks/use-async-effect.d.ts +24 -0
  230. package/src/lib/hooks/use-async-effect.js +44 -0
  231. package/src/lib/hooks/use-async-effect.js.map +1 -0
  232. package/src/lib/hooks/use-callback-param-ref.d.ts +19 -0
  233. package/src/lib/hooks/use-callback-param-ref.js +29 -0
  234. package/src/lib/hooks/use-callback-param-ref.js.map +1 -0
  235. package/src/lib/hooks/use-id.d.ts +21 -0
  236. package/src/lib/hooks/use-id.js +28 -0
  237. package/src/lib/hooks/use-id.js.map +1 -0
  238. package/src/lib/hooks/use-isomorphic-layout-effect.d.ts +19 -0
  239. package/src/lib/hooks/use-isomorphic-layout-effect.js +20 -0
  240. package/src/lib/hooks/use-isomorphic-layout-effect.js.map +1 -0
  241. package/src/lib/hooks/use-merge-refs.d.ts +38 -0
  242. package/src/lib/hooks/use-merge-refs.js +52 -0
  243. package/src/lib/hooks/use-merge-refs.js.map +1 -0
  244. package/src/lib/hooks/use-subscribable.d.ts +29 -0
  245. package/src/lib/hooks/use-subscribable.js +50 -0
  246. package/src/lib/hooks/use-subscribable.js.map +1 -0
  247. package/src/lib/types.d.ts +18 -0
  248. package/src/lib/types.js +18 -0
  249. package/src/lib/types.js.map +1 -0
  250. package/src/lib/utils/make-link-elements.d.ts +24 -0
  251. package/src/lib/utils/make-link-elements.js +32 -0
  252. package/src/lib/utils/make-link-elements.js.map +1 -0
  253. package/src/lib/utils/make-meta-elements.d.ts +24 -0
  254. package/src/lib/utils/make-meta-elements.js +32 -0
  255. package/src/lib/utils/make-meta-elements.js.map +1 -0
  256. package/src/lib/utils/scroll-overflow.d.ts +120 -0
  257. package/src/lib/utils/scroll-overflow.js +115 -0
  258. package/src/lib/utils/scroll-overflow.js.map +1 -0
  259. package/src/lib/utils/vendor.d.ts +17 -0
  260. package/src/lib/utils/vendor.js +18 -0
  261. package/src/lib/utils/vendor.js.map +1 -0
@@ -0,0 +1,409 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { getGridBooleanOperators, getGridDateOperators, getGridNumericOperators, getGridStringOperators } from "@mui/x-data-grid";
18
+ /** The empty-operators a field can honestly offer. See `presence`. */ const emptyOperators = (field)=>{
19
+ var _field_presence;
20
+ switch((_field_presence = field.presence) != null ? _field_presence : 'sparse'){
21
+ case 'always':
22
+ return [];
23
+ case 'nullable':
24
+ return [
25
+ 'isEmpty',
26
+ 'isNotEmpty'
27
+ ];
28
+ default:
29
+ return [
30
+ 'isNotEmpty'
31
+ ];
32
+ }
33
+ };
34
+ /** The operators a field offers, derived from the paths it actually has. */ export function listFilterOperators(field) {
35
+ if (field.operators) return [
36
+ ...field.operators
37
+ ];
38
+ const empties = emptyOperators(field);
39
+ switch(field.kind){
40
+ case 'text':
41
+ return [
42
+ ...field.tokensPath ? [
43
+ 'contains'
44
+ ] : [],
45
+ ...field.lowerPath ? [
46
+ 'equals',
47
+ 'startsWith'
48
+ ] : [],
49
+ ...field.reversedPath ? [
50
+ 'endsWith'
51
+ ] : [],
52
+ ...empties
53
+ ];
54
+ case 'exact':
55
+ return [
56
+ 'equals',
57
+ 'isAnyOf',
58
+ ...empties
59
+ ];
60
+ case 'id':
61
+ // An id is never absent, so the empty operators would answer nothing.
62
+ return [
63
+ 'equals',
64
+ 'startsWith',
65
+ 'isAnyOf'
66
+ ];
67
+ case 'boolean':
68
+ return [
69
+ 'is'
70
+ ];
71
+ case 'number':
72
+ return [
73
+ '=',
74
+ '!=',
75
+ '>',
76
+ '>=',
77
+ '<',
78
+ '<=',
79
+ ...empties
80
+ ];
81
+ case 'date':
82
+ return [
83
+ 'is',
84
+ 'after',
85
+ 'onOrAfter',
86
+ 'before',
87
+ 'onOrBefore',
88
+ ...empties
89
+ ];
90
+ default:
91
+ return [];
92
+ }
93
+ }
94
+ const operatorPool = (kind)=>{
95
+ switch(kind){
96
+ case 'boolean':
97
+ return getGridBooleanOperators();
98
+ case 'number':
99
+ return getGridNumericOperators();
100
+ case 'date':
101
+ return getGridDateOperators();
102
+ default:
103
+ return getGridStringOperators();
104
+ }
105
+ };
106
+ /**
107
+ * The MUI operators for a field — the same list `listFilterOperators` names,
108
+ * resolved to the grid's own operator objects so the panel keeps its native
109
+ * inputs (a date picker for a date, a number field for a number).
110
+ */ export function gridFilterOperators(field) {
111
+ const allowed = listFilterOperators(field);
112
+ return operatorPool(field.kind).filter((operator)=>allowed.includes(operator.value));
113
+ }
114
+ /**
115
+ * Spread onto a `GridColDef` to make a column filterable exactly as far as the
116
+ * query can serve it. A column with NO declared field is turned off entirely —
117
+ * deliberately, because the alternative is a funnel icon that opens a panel
118
+ * nothing honours.
119
+ */ export function listFilterColumn(fields, column) {
120
+ const field = fields.find((entry)=>entry.column === column);
121
+ if (!field) return {
122
+ filterable: false
123
+ };
124
+ const operators = gridFilterOperators(field);
125
+ return operators.length ? {
126
+ filterable: true,
127
+ filterOperators: operators
128
+ } : {
129
+ filterable: false
130
+ };
131
+ }
132
+ /** Operators that carry no value — the grid leaves `item.value` undefined. */ const VALUELESS = [
133
+ 'isEmpty',
134
+ 'isNotEmpty'
135
+ ];
136
+ /**
137
+ * The one filter item a server-paged list can act on, read off a grid model.
138
+ *
139
+ * ONE, because Firestore composes predicates only through indexes nobody built
140
+ * for every pair of columns; the first usable item wins and the rest are the
141
+ * reader's to remove. Every list read this off the model itself, and each did
142
+ * it slightly differently — the common miss being `isEmpty`, which sets no
143
+ * value at all and so was skipped by any check that required one.
144
+ */ export function gridFilterRequest(model) {
145
+ var _model_items;
146
+ const usable = ((_model_items = model.items) != null ? _model_items : []).find((item)=>{
147
+ if (!item.field || !item.operator) return false;
148
+ if (VALUELESS.includes(String(item.operator))) return true;
149
+ if (item.value === undefined || item.value === null) return false;
150
+ return Array.isArray(item.value) ? item.value.length > 0 : String(item.value).trim() !== '';
151
+ });
152
+ if (!usable) return null;
153
+ return gridItemRequest(usable);
154
+ }
155
+ /** Whether a grid filter item asks anything at all — see `gridFilterRequest`. */ const gridItemUsable = (item)=>{
156
+ if (!item.field || !item.operator) return false;
157
+ if (VALUELESS.includes(String(item.operator))) return true;
158
+ if (item.value === undefined || item.value === null) return false;
159
+ return Array.isArray(item.value) ? item.value.length > 0 : String(item.value).trim() !== '';
160
+ };
161
+ const gridItemRequest = (item)=>{
162
+ const raw = item.value;
163
+ const value = Array.isArray(raw) ? raw.join(',') : // locale rendering the server would have to guess at. ISO travels
164
+ // unambiguously and `new Date` reads it back exactly.
165
+ raw instanceof Date ? raw.toISOString() : raw === undefined || raw === null ? '' : String(raw);
166
+ return {
167
+ field: String(item.field),
168
+ op: String(item.operator),
169
+ value
170
+ };
171
+ };
172
+ /**
173
+ * EVERY usable filter item on a grid model, in the order the panel holds
174
+ * them — for a list that keeps more than one clause (AGL-2617).
175
+ *
176
+ * The singular reader above picks the first because a query serves one;
177
+ * a saved view carries a list of clauses and a list that applies it puts
178
+ * the first servable one on the query and matches the rest over the rows
179
+ * it loaded, which `listFilterPlan` in the instance library decides. The
180
+ * two readers share one notion of "usable", so a clause the singular one
181
+ * would take is a clause this one keeps.
182
+ */ export function gridFilterRequests(model) {
183
+ var _model_items;
184
+ return ((_model_items = model.items) != null ? _model_items : []).filter(gridItemUsable).map(gridItemRequest);
185
+ }
186
+ /**
187
+ * How an operator reads on a chip or in a sentence — "Owner is Dana",
188
+ * "Created on or after 1 Jan". One map so every list that shows its
189
+ * clauses back spells them the same way; an operator nothing here names
190
+ * is shown as itself rather than hidden.
191
+ */ export function listFilterOperatorLabel(op) {
192
+ switch(op){
193
+ case 'contains':
194
+ return 'contains';
195
+ case 'doesNotContain':
196
+ return 'does not contain';
197
+ case 'equals':
198
+ case 'is':
199
+ case '=':
200
+ return 'is';
201
+ case 'doesNotEqual':
202
+ case '!=':
203
+ return 'is not';
204
+ case 'startsWith':
205
+ return 'starts with';
206
+ case 'endsWith':
207
+ return 'ends with';
208
+ case 'isAnyOf':
209
+ return 'is any of';
210
+ case 'isEmpty':
211
+ return 'is empty';
212
+ case 'isNotEmpty':
213
+ return 'is set';
214
+ case 'after':
215
+ return 'after';
216
+ case 'onOrAfter':
217
+ return 'on or after';
218
+ case 'before':
219
+ return 'before';
220
+ case 'onOrBefore':
221
+ return 'on or before';
222
+ case '>':
223
+ return 'over';
224
+ case '>=':
225
+ return 'at least';
226
+ case '<':
227
+ return 'under';
228
+ case '<=':
229
+ return 'at most';
230
+ default:
231
+ return op;
232
+ }
233
+ }
234
+ /**
235
+ * Fields a reader can filter by that are NOT columns on the table.
236
+ *
237
+ * MUI's filter panel lists COLUMNS — `gridFilterableColumnDefinitionsSelector`
238
+ * reads every column definition, hidden ones included — so a filterable field
239
+ * with no column is a field nobody can reach however well the route answers it.
240
+ * Declaring it as a permanently hidden column keeps one source of truth, the
241
+ * field list, instead of a second list of "extra filters" that drifts from it.
242
+ *
243
+ * `hideable: false` keeps them out of Manage columns as well: a column with no
244
+ * `renderCell` and no width has nothing to show, and a reader who unhid one
245
+ * would get a strip of blank cells for their trouble.
246
+ *
247
+ * Pair with {@link hiddenFilterVisibility}, which is what actually hides them.
248
+ */ export function hiddenFilterColumns(fields, visible, headers = {}) {
249
+ return fields.filter((field)=>!visible.includes(field.column)).map((field)=>{
250
+ var _headers_field_column;
251
+ return _extends({
252
+ field: field.column,
253
+ headerName: (_headers_field_column = headers[field.column]) != null ? _headers_field_column : field.column,
254
+ hideable: false
255
+ }, listFilterColumn(fields, field.column));
256
+ }).filter((column)=>column.filterable);
257
+ }
258
+ const readPath = (row, path)=>path.split('.').reduce((value, key)=>value == null ? undefined : value[key], row);
259
+ const asTime = (value)=>{
260
+ if (value == null) return null;
261
+ if (value instanceof Date) return value.getTime();
262
+ if (typeof value === 'number') return value;
263
+ // A Firestore timestamp, in either the admin shape or the serialized one.
264
+ const seconds = value.seconds;
265
+ if (typeof seconds === 'number') return seconds * 1000;
266
+ const parsed = new Date(String(value)).getTime();
267
+ return Number.isNaN(parsed) ? null : parsed;
268
+ };
269
+ /**
270
+ * Match ONE row against a filter, for a list that cannot push it to a query.
271
+ *
272
+ * The staff account list is the reason this exists: it is Firebase Auth, whose
273
+ * `listUsers` takes a page size and a cursor and nothing else — no predicate,
274
+ * no ordering, no search. A filter there is answered by walking the pools and
275
+ * matching here, which is why that list can offer a mid-string `contains` and
276
+ * a `doesNotContain` that a Firestore-backed list cannot.
277
+ *
278
+ * The declaration is still the same `ListFilterField`, so a list swapping
279
+ * substrates changes where the matching happens and not what it offers.
280
+ */ export function matchListFilter(row, fields, input) {
281
+ var _field_rowPath, _input_value;
282
+ if (!input) return true;
283
+ const field = fields.find((entry)=>entry.column === input.field);
284
+ if (!field) return true;
285
+ const stored = readPath(row, (_field_rowPath = field.rowPath) != null ? _field_rowPath : field.path);
286
+ // A presence map is matched as the array of its truthy keys — see `keysOf`.
287
+ const value = field.keysOf && stored && typeof stored === 'object' && !Array.isArray(stored) ? Object.keys(stored).filter((key)=>Boolean(stored[key])) : stored;
288
+ const op = input.op;
289
+ const blank = value == null || value === '' || Array.isArray(value) && value.length === 0;
290
+ if (op === 'isEmpty') return blank;
291
+ if (op === 'isNotEmpty') return !blank;
292
+ const raw = ((_input_value = input.value) != null ? _input_value : '').trim();
293
+ if (field.kind === 'boolean') {
294
+ if (raw !== 'true' && raw !== 'false') return true;
295
+ return Boolean(value) === (raw === 'true');
296
+ }
297
+ if (!raw) return true;
298
+ /*
299
+ * An array the QUERY serves whole is matched by whole member, never by
300
+ * substring of its joined form. A tag array asked `contains vip` holds the
301
+ * tag `vip` or it does not — `vip-gold` is a different tag, and the
302
+ * query's `array-contains` says so too, so the in-memory answer and the
303
+ * served answer agree. An id array keeps its case (`verbatimTokens`); a
304
+ * word array is folded the way its writer folded it. `isAnyOf` is any
305
+ * member in the asked list, which is what a saved segment's "any of these
306
+ * tags" becomes as a view clause. A presence map's keys are members too.
307
+ *
308
+ * A plain array with no token path is served by nothing, so there is no
309
+ * query to agree with, and it falls through to the scalar match over its
310
+ * joined text — the staff account list's providers, where `contains
311
+ * google` finding `google.com` is the mid-string answer that list
312
+ * documents (`operators`).
313
+ */ if (Array.isArray(value) && (field.tokensPath || field.keysOf)) {
314
+ const fold = (entry)=>field.verbatimTokens ? String(entry) : String(entry).toLowerCase();
315
+ const members = value.map(fold);
316
+ const asked = fold(raw);
317
+ switch(op){
318
+ case 'contains':
319
+ case 'equals':
320
+ case 'is':
321
+ return members.includes(asked);
322
+ case 'doesNotContain':
323
+ case 'doesNotEqual':
324
+ return !members.includes(asked);
325
+ case 'isAnyOf':
326
+ return asked.split(',').map((entry)=>entry.trim()).filter(Boolean).some((entry)=>members.includes(entry));
327
+ default:
328
+ return true;
329
+ }
330
+ }
331
+ if (field.kind === 'date') {
332
+ const at = asTime(value);
333
+ const day = new Date(raw);
334
+ if (at === null || Number.isNaN(day.getTime())) return false;
335
+ const start = new Date(day);
336
+ start.setHours(0, 0, 0, 0);
337
+ const end = new Date(start);
338
+ end.setDate(end.getDate() + 1);
339
+ switch(op){
340
+ // A day, not an instant — a stored time never equals midnight.
341
+ case 'is':
342
+ return at >= start.getTime() && at < end.getTime();
343
+ case 'after':
344
+ return at >= end.getTime();
345
+ case 'onOrAfter':
346
+ return at >= start.getTime();
347
+ case 'before':
348
+ return at < start.getTime();
349
+ case 'onOrBefore':
350
+ return at < end.getTime();
351
+ default:
352
+ return true;
353
+ }
354
+ }
355
+ if (field.kind === 'number') {
356
+ const asked = Number(raw);
357
+ const held = Number(value);
358
+ if (!Number.isFinite(asked) || !Number.isFinite(held)) return false;
359
+ switch(op){
360
+ case '=':
361
+ return held === asked;
362
+ case '!=':
363
+ return held !== asked;
364
+ case '>':
365
+ return held > asked;
366
+ case '>=':
367
+ return held >= asked;
368
+ case '<':
369
+ return held < asked;
370
+ case '<=':
371
+ return held <= asked;
372
+ default:
373
+ return true;
374
+ }
375
+ }
376
+ // A scalar id is matched as typed — see `verbatimTokens`; the array case
377
+ // was answered above.
378
+ if (field.verbatimTokens && op === 'contains') return value === raw;
379
+ const held = value == null ? '' : String(value).toLowerCase();
380
+ const asked = raw.toLowerCase();
381
+ switch(op){
382
+ case 'contains':
383
+ return held.includes(asked);
384
+ case 'doesNotContain':
385
+ return !held.includes(asked);
386
+ case 'equals':
387
+ return held === asked;
388
+ case 'doesNotEqual':
389
+ return held !== asked;
390
+ case 'startsWith':
391
+ return held.startsWith(asked);
392
+ case 'endsWith':
393
+ return held.endsWith(asked);
394
+ case 'isAnyOf':
395
+ return asked.split(',').map((entry)=>entry.trim()).filter(Boolean).includes(held);
396
+ default:
397
+ // An operator nothing here answers must not narrow the list to
398
+ // nothing — that reads as "no such record" rather than "not supported".
399
+ return true;
400
+ }
401
+ }
402
+ /** The visibility model that hides what {@link hiddenFilterColumns} added. */ export function hiddenFilterVisibility(fields, visible) {
403
+ return Object.fromEntries(fields.filter((field)=>!visible.includes(field.column)).map((field)=>[
404
+ field.column,
405
+ false
406
+ ]));
407
+ }
408
+
409
+ //# sourceMappingURL=list-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/const/list-filter.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n getGridBooleanOperators,\n getGridDateOperators,\n getGridNumericOperators,\n getGridStringOperators,\n type GridFilterOperator,\n} from '@mui/x-data-grid'\n\n/**\n * ONE declaration of what a paged list can be filtered by (AGL-2501).\n *\n * A paged list filters on the SERVER or it does not filter: `filterMode=\"server\"`\n * stops the grid narrowing anything itself, so the panel shows the rows already\n * fetched — ten of them by default — and an operator the route does not answer\n * becomes a control that quietly does nothing. On a staff list whose whole job\n * is that nobody is missing, \"no matches\" is the one answer it must never give\n * wrongly.\n *\n * So a list declares its filterable fields ONCE, in a module both its route and\n * its page import. The declaration decides two things that must never disagree:\n * which operators the menu offers (here) and which predicates the query builds\n * (`applyListFilter`, server-side, which needs firebase-admin and so cannot\n * live in this file).\n *\n * ## Why the menu is shorter than MUI's\n *\n * Firestore has equality, `in`, ranges and `array-contains`. Everything below\n * is built from those four:\n *\n * equals / isAnyOf equality and `in` (Firestore caps `in` at 30 values)\n * startsWith a range over the normalized lower-case key\n * endsWith a range over the key stored REVERSED — a range is\n * anchored at the FRONT of a value, so storing the value\n * backwards is the only way to ask about its end\n * contains `array-contains` over word-prefix tokens, so it is\n * WORD-level: \"coffee\" finds \"Acme Coffee\", \"offee\" does\n * not find anything\n * before / after ranges on a timestamp or a number\n * isNotEmpty `!= null`, which in Firestore also requires the field to\n * EXIST — which is the meaning wanted\n *\n * ⛔ `doesNotContain` is offered nowhere and cannot be. Firestore has no\n * negated substring match, and no denormalization fixes it: the inverse of a\n * token array is every string the value does not contain, which is unbounded.\n *\n * ⚠️ The two empty operators depend on how a field's WRITERS behave, which is\n * what `presence` declares. Firestore cannot query for absence at all:\n * `where(path, '==', null)` matches an explicit null and never a missing field,\n * while `where(path, '!=', null)` additionally requires the field to exist.\n * So a field that writers omit can answer `isNotEmpty` exactly and can never\n * answer `isEmpty` — it would say \"none\" to a question with real answers — and\n * a field that is always written answers both, but each with a foregone\n * result. Only a `nullable` field earns both operators for real.\n */\n\n/** How a field can be queried, which decides which operators it offers. */\nexport type ListFilterKind =\n | 'text'\n | 'exact'\n | 'boolean'\n | 'number'\n | 'date'\n | 'id'\n\nexport interface ListFilterField {\n /** The grid column's `field` — what the client sends back. */\n column: string\n kind: ListFilterKind\n /** The Firestore field path the predicate targets. */\n path: string\n /**\n * The normalized lower-case twin, for `equals` and `startsWith` on text.\n * Without one a text field offers neither: a raw value is case-sensitive, so\n * it would miss rather than fail.\n */\n lowerPath?: string\n /** Word-prefix token array, for `contains`. */\n tokensPath?: string\n /**\n * The token array holds OPAQUE IDS, matched byte for byte.\n *\n * A word token array is lower-cased by its writer, so a `contains` folds\n * the typed value the same way before it looks. An id array — the forms a\n * contact came in through, the companies they are linked to — is not: the\n * ids are minted with mixed case, and folding one would look up an id\n * nothing wrote. A field that says so is matched on the value exactly as\n * given, in the query and in memory alike.\n */\n verbatimTokens?: boolean\n /**\n * What a `contains` orders by. Defaults to `lowerPath`, then `path`.\n *\n * A field whose `tokensPath` IS its own value — a real tag array, matched\n * whole rather than by word prefix — has no lower-case twin to sort by, and\n * defaulting to `path` would order by the array itself. Naming a scalar here\n * keeps the composite index that combination needs an ordinary one.\n */\n containsOrderBy?: string\n /** The reversed key, for `endsWith`. */\n reversedPath?: string\n /**\n * How the field's writers treat \"no value\", which is the only thing that\n * decides whether the empty operators mean anything:\n *\n * `sparse` (default) writers OMIT the field. `isNotEmpty` is exact;\n * `isEmpty` is unanswerable and so is not offered.\n * `nullable` writers store `null`. Both operators are exact and both can\n * return rows — the only case where offering them is useful.\n * `always` the field is never absent and never null. Both operators have\n * a foregone answer (all rows, then none), so neither is\n * offered: a control whose result is known is a control that\n * wastes the reader's time.\n */\n presence?: 'sparse' | 'nullable' | 'always'\n /**\n * The operators this field offers, replacing the derived list.\n *\n * Not every list is a Firestore query. The staff account list is Firebase\n * Auth, which cannot filter at ALL — so a filter there is answered by\n * scanning the pools and matching in memory, and plain JavaScript can do\n * things no index can: a mid-string `contains`, and `doesNotContain`. A\n * list whose substrate is more capable says so here rather than being held\n * to Firestore's limits by a shared default.\n *\n * Pair with {@link matchListFilter}, which is the matcher those lists use.\n */\n operators?: readonly string[]\n /**\n * Where to read this field from a ROW, when the list matches in memory.\n * Defaults to `path`. Only needed when the row's shape differs from the\n * document's — an Auth record's `staff` lives under `customClaims`.\n */\n rowPath?: string\n /**\n * The field lives where no query can reach it, so the list matches it\n * over the rows it has loaded and the translators refuse it.\n *\n * A contact's owner, stage and custom values sit on the viewing group's\n * FACET — a map keyed per group — and a `where` on a per-group path would\n * need an index per group. Declaring the field at all is what puts it in\n * the menu and in a saved view; saying it is window-only is what keeps a\n * clause on it from being sent to a query that would answer with a\n * permission error or nothing. The list says which clauses narrowed only\n * the window — see `listFilterPlan`.\n */\n windowOnly?: boolean\n /**\n * The stored value is a PRESENCE MAP — `{ form: true, order: true }` —\n * and the filter asks about its keys.\n *\n * A contact's `sources` is such a map: one key per door the person came\n * in through, never an array. Matched as though it were the array of its\n * truthy keys, so `equals form` and `isAnyOf form,order` read the way a\n * reader expects; a query can serve `equals` as `sources.form == true`.\n */\n keysOf?: boolean\n}\n\n/** The empty-operators a field can honestly offer. See `presence`. */\nconst emptyOperators = (field: ListFilterField): string[] => {\n switch (field.presence ?? 'sparse') {\n case 'always':\n return []\n case 'nullable':\n return ['isEmpty', 'isNotEmpty']\n default:\n return ['isNotEmpty']\n }\n}\n\n/** The operators a field offers, derived from the paths it actually has. */\nexport function listFilterOperators(field: ListFilterField): string[] {\n if (field.operators) return [...field.operators]\n const empties = emptyOperators(field)\n switch (field.kind) {\n case 'text':\n return [\n ...(field.tokensPath ? ['contains'] : []),\n ...(field.lowerPath ? ['equals', 'startsWith'] : []),\n ...(field.reversedPath ? ['endsWith'] : []),\n ...empties,\n ]\n case 'exact':\n return ['equals', 'isAnyOf', ...empties]\n case 'id':\n // An id is never absent, so the empty operators would answer nothing.\n return ['equals', 'startsWith', 'isAnyOf']\n case 'boolean':\n return ['is']\n case 'number':\n return ['=', '!=', '>', '>=', '<', '<=', ...empties]\n case 'date':\n return ['is', 'after', 'onOrAfter', 'before', 'onOrBefore', ...empties]\n default:\n return []\n }\n}\n\nconst operatorPool = (kind: ListFilterKind): GridFilterOperator[] => {\n switch (kind) {\n case 'boolean':\n return getGridBooleanOperators()\n case 'number':\n return getGridNumericOperators()\n case 'date':\n return getGridDateOperators()\n default:\n return getGridStringOperators()\n }\n}\n\n/**\n * The MUI operators for a field — the same list `listFilterOperators` names,\n * resolved to the grid's own operator objects so the panel keeps its native\n * inputs (a date picker for a date, a number field for a number).\n */\nexport function gridFilterOperators(\n field: ListFilterField,\n): GridFilterOperator[] {\n const allowed = listFilterOperators(field)\n return operatorPool(field.kind).filter((operator) =>\n allowed.includes(operator.value),\n )\n}\n\n/**\n * Spread onto a `GridColDef` to make a column filterable exactly as far as the\n * query can serve it. A column with NO declared field is turned off entirely —\n * deliberately, because the alternative is a funnel icon that opens a panel\n * nothing honours.\n */\nexport function listFilterColumn(\n fields: readonly ListFilterField[],\n column: string,\n): { filterable: boolean; filterOperators?: GridFilterOperator[] } {\n const field = fields.find((entry) => entry.column === column)\n if (!field) return { filterable: false }\n const operators = gridFilterOperators(field)\n return operators.length\n ? { filterable: true, filterOperators: operators }\n : { filterable: false }\n}\n\n/** What a page sends the route: one field, one operator, one value. */\nexport interface ListFilterRequest {\n field: string\n op: string\n value: string\n}\n\n/** Operators that carry no value — the grid leaves `item.value` undefined. */\nconst VALUELESS = ['isEmpty', 'isNotEmpty']\n\n/**\n * The one filter item a server-paged list can act on, read off a grid model.\n *\n * ONE, because Firestore composes predicates only through indexes nobody built\n * for every pair of columns; the first usable item wins and the rest are the\n * reader's to remove. Every list read this off the model itself, and each did\n * it slightly differently — the common miss being `isEmpty`, which sets no\n * value at all and so was skipped by any check that required one.\n */\nexport function gridFilterRequest(model: {\n items?: Array<{ field?: unknown; operator?: unknown; value?: unknown }>\n}): ListFilterRequest | null {\n const usable = (model.items ?? []).find((item) => {\n if (!item.field || !item.operator) return false\n if (VALUELESS.includes(String(item.operator))) return true\n if (item.value === undefined || item.value === null) return false\n return Array.isArray(item.value)\n ? item.value.length > 0\n : String(item.value).trim() !== ''\n })\n if (!usable) return null\n return gridItemRequest(usable)\n}\n\n/** Whether a grid filter item asks anything at all — see `gridFilterRequest`. */\nconst gridItemUsable = (item: {\n field?: unknown\n operator?: unknown\n value?: unknown\n}): boolean => {\n if (!item.field || !item.operator) return false\n if (VALUELESS.includes(String(item.operator))) return true\n if (item.value === undefined || item.value === null) return false\n return Array.isArray(item.value)\n ? item.value.length > 0\n : String(item.value).trim() !== ''\n}\n\nconst gridItemRequest = (item: {\n field?: unknown\n operator?: unknown\n value?: unknown\n}): ListFilterRequest => {\n const raw = item.value\n const value = Array.isArray(raw)\n ? raw.join(',')\n : // A date column hands back a `Date`, whose default string form is a\n // locale rendering the server would have to guess at. ISO travels\n // unambiguously and `new Date` reads it back exactly.\n raw instanceof Date\n ? raw.toISOString()\n : raw === undefined || raw === null\n ? ''\n : String(raw)\n return { field: String(item.field), op: String(item.operator), value }\n}\n\n/**\n * EVERY usable filter item on a grid model, in the order the panel holds\n * them — for a list that keeps more than one clause (AGL-2617).\n *\n * The singular reader above picks the first because a query serves one;\n * a saved view carries a list of clauses and a list that applies it puts\n * the first servable one on the query and matches the rest over the rows\n * it loaded, which `listFilterPlan` in the instance library decides. The\n * two readers share one notion of \"usable\", so a clause the singular one\n * would take is a clause this one keeps.\n */\nexport function gridFilterRequests(model: {\n items?: Array<{ field?: unknown; operator?: unknown; value?: unknown }>\n}): ListFilterRequest[] {\n return (model.items ?? []).filter(gridItemUsable).map(gridItemRequest)\n}\n\n/**\n * How an operator reads on a chip or in a sentence — \"Owner is Dana\",\n * \"Created on or after 1 Jan\". One map so every list that shows its\n * clauses back spells them the same way; an operator nothing here names\n * is shown as itself rather than hidden.\n */\nexport function listFilterOperatorLabel(op: string): string {\n switch (op) {\n case 'contains':\n return 'contains'\n case 'doesNotContain':\n return 'does not contain'\n case 'equals':\n case 'is':\n case '=':\n return 'is'\n case 'doesNotEqual':\n case '!=':\n return 'is not'\n case 'startsWith':\n return 'starts with'\n case 'endsWith':\n return 'ends with'\n case 'isAnyOf':\n return 'is any of'\n case 'isEmpty':\n return 'is empty'\n case 'isNotEmpty':\n return 'is set'\n case 'after':\n return 'after'\n case 'onOrAfter':\n return 'on or after'\n case 'before':\n return 'before'\n case 'onOrBefore':\n return 'on or before'\n case '>':\n return 'over'\n case '>=':\n return 'at least'\n case '<':\n return 'under'\n case '<=':\n return 'at most'\n default:\n return op\n }\n}\n\n/**\n * Fields a reader can filter by that are NOT columns on the table.\n *\n * MUI's filter panel lists COLUMNS — `gridFilterableColumnDefinitionsSelector`\n * reads every column definition, hidden ones included — so a filterable field\n * with no column is a field nobody can reach however well the route answers it.\n * Declaring it as a permanently hidden column keeps one source of truth, the\n * field list, instead of a second list of \"extra filters\" that drifts from it.\n *\n * `hideable: false` keeps them out of Manage columns as well: a column with no\n * `renderCell` and no width has nothing to show, and a reader who unhid one\n * would get a strip of blank cells for their trouble.\n *\n * Pair with {@link hiddenFilterVisibility}, which is what actually hides them.\n */\nexport function hiddenFilterColumns(\n fields: readonly ListFilterField[],\n visible: readonly string[],\n headers: Readonly<Record<string, string>> = {},\n): Array<{\n field: string\n headerName: string\n hideable: boolean\n filterable: boolean\n filterOperators?: GridFilterOperator[]\n}> {\n return fields\n .filter((field) => !visible.includes(field.column))\n .map((field) => ({\n field: field.column,\n headerName: headers[field.column] ?? field.column,\n hideable: false,\n ...listFilterColumn(fields, field.column),\n }))\n .filter((column) => column.filterable)\n}\n\nconst readPath = (row: unknown, path: string): unknown =>\n path\n .split('.')\n .reduce<any>(\n (value, key) => (value == null ? undefined : value[key]),\n row as any,\n )\n\nconst asTime = (value: unknown): number | null => {\n if (value == null) return null\n if (value instanceof Date) return value.getTime()\n if (typeof value === 'number') return value\n // A Firestore timestamp, in either the admin shape or the serialized one.\n const seconds = (value as { seconds?: unknown }).seconds\n if (typeof seconds === 'number') return seconds * 1000\n const parsed = new Date(String(value)).getTime()\n return Number.isNaN(parsed) ? null : parsed\n}\n\n/**\n * Match ONE row against a filter, for a list that cannot push it to a query.\n *\n * The staff account list is the reason this exists: it is Firebase Auth, whose\n * `listUsers` takes a page size and a cursor and nothing else — no predicate,\n * no ordering, no search. A filter there is answered by walking the pools and\n * matching here, which is why that list can offer a mid-string `contains` and\n * a `doesNotContain` that a Firestore-backed list cannot.\n *\n * The declaration is still the same `ListFilterField`, so a list swapping\n * substrates changes where the matching happens and not what it offers.\n */\nexport function matchListFilter(\n row: unknown,\n fields: readonly ListFilterField[],\n input: ListFilterRequest | null,\n): boolean {\n if (!input) return true\n const field = fields.find((entry) => entry.column === input.field)\n if (!field) return true\n const stored = readPath(row, field.rowPath ?? field.path)\n // A presence map is matched as the array of its truthy keys — see `keysOf`.\n const value =\n field.keysOf && stored && typeof stored === 'object' && !Array.isArray(stored)\n ? Object.keys(stored as Record<string, unknown>).filter((key) =>\n Boolean((stored as Record<string, unknown>)[key]),\n )\n : stored\n const op = input.op\n\n const blank =\n value == null || value === '' || (Array.isArray(value) && value.length === 0)\n if (op === 'isEmpty') return blank\n if (op === 'isNotEmpty') return !blank\n\n const raw = (input.value ?? '').trim()\n if (field.kind === 'boolean') {\n if (raw !== 'true' && raw !== 'false') return true\n return Boolean(value) === (raw === 'true')\n }\n if (!raw) return true\n\n /*\n * An array the QUERY serves whole is matched by whole member, never by\n * substring of its joined form. A tag array asked `contains vip` holds the\n * tag `vip` or it does not — `vip-gold` is a different tag, and the\n * query's `array-contains` says so too, so the in-memory answer and the\n * served answer agree. An id array keeps its case (`verbatimTokens`); a\n * word array is folded the way its writer folded it. `isAnyOf` is any\n * member in the asked list, which is what a saved segment's \"any of these\n * tags\" becomes as a view clause. A presence map's keys are members too.\n *\n * A plain array with no token path is served by nothing, so there is no\n * query to agree with, and it falls through to the scalar match over its\n * joined text — the staff account list's providers, where `contains\n * google` finding `google.com` is the mid-string answer that list\n * documents (`operators`).\n */\n if (Array.isArray(value) && (field.tokensPath || field.keysOf)) {\n const fold = (entry: unknown) =>\n field.verbatimTokens ? String(entry) : String(entry).toLowerCase()\n const members = value.map(fold)\n const asked = fold(raw)\n switch (op) {\n case 'contains':\n case 'equals':\n case 'is':\n return members.includes(asked)\n case 'doesNotContain':\n case 'doesNotEqual':\n return !members.includes(asked)\n case 'isAnyOf':\n return asked\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n .some((entry) => members.includes(entry))\n default:\n return true\n }\n }\n\n if (field.kind === 'date') {\n const at = asTime(value)\n const day = new Date(raw)\n if (at === null || Number.isNaN(day.getTime())) return false\n const start = new Date(day)\n start.setHours(0, 0, 0, 0)\n const end = new Date(start)\n end.setDate(end.getDate() + 1)\n switch (op) {\n // A day, not an instant — a stored time never equals midnight.\n case 'is':\n return at >= start.getTime() && at < end.getTime()\n case 'after':\n return at >= end.getTime()\n case 'onOrAfter':\n return at >= start.getTime()\n case 'before':\n return at < start.getTime()\n case 'onOrBefore':\n return at < end.getTime()\n default:\n return true\n }\n }\n\n if (field.kind === 'number') {\n const asked = Number(raw)\n const held = Number(value)\n if (!Number.isFinite(asked) || !Number.isFinite(held)) return false\n switch (op) {\n case '=':\n return held === asked\n case '!=':\n return held !== asked\n case '>':\n return held > asked\n case '>=':\n return held >= asked\n case '<':\n return held < asked\n case '<=':\n return held <= asked\n default:\n return true\n }\n }\n\n // A scalar id is matched as typed — see `verbatimTokens`; the array case\n // was answered above.\n if (field.verbatimTokens && op === 'contains') return value === raw\n const held = value == null ? '' : String(value).toLowerCase()\n const asked = raw.toLowerCase()\n switch (op) {\n case 'contains':\n return held.includes(asked)\n case 'doesNotContain':\n return !held.includes(asked)\n case 'equals':\n return held === asked\n case 'doesNotEqual':\n return held !== asked\n case 'startsWith':\n return held.startsWith(asked)\n case 'endsWith':\n return held.endsWith(asked)\n case 'isAnyOf':\n return asked\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n .includes(held)\n default:\n // An operator nothing here answers must not narrow the list to\n // nothing — that reads as \"no such record\" rather than \"not supported\".\n return true\n }\n}\n\n/** The visibility model that hides what {@link hiddenFilterColumns} added. */\nexport function hiddenFilterVisibility(\n fields: readonly ListFilterField[],\n visible: readonly string[],\n): Record<string, boolean> {\n return Object.fromEntries(\n fields\n .filter((field) => !visible.includes(field.column))\n .map((field) => [field.column, false]),\n )\n}\n"],"names":["getGridBooleanOperators","getGridDateOperators","getGridNumericOperators","getGridStringOperators","emptyOperators","field","presence","listFilterOperators","operators","empties","kind","tokensPath","lowerPath","reversedPath","operatorPool","gridFilterOperators","allowed","filter","operator","includes","value","listFilterColumn","fields","column","find","entry","filterable","length","filterOperators","VALUELESS","gridFilterRequest","model","usable","items","item","String","undefined","Array","isArray","trim","gridItemRequest","gridItemUsable","raw","join","Date","toISOString","op","gridFilterRequests","map","listFilterOperatorLabel","hiddenFilterColumns","visible","headers","headerName","hideable","readPath","row","path","split","reduce","key","asTime","getTime","seconds","parsed","Number","isNaN","matchListFilter","input","stored","rowPath","keysOf","Object","keys","Boolean","blank","fold","verbatimTokens","toLowerCase","members","asked","some","at","day","start","setHours","end","setDate","getDate","held","isFinite","startsWith","endsWith","hiddenFilterVisibility","fromEntries"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export declare const LOADING_OVERLAY_ELEMENT: import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * @license
4
+ * Copyright 2023 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import LoadingModal from "../components/loading-modal.js";
18
+ export const LOADING_OVERLAY_ELEMENT = /*#__PURE__*/ _jsx(LoadingModal, {
19
+ open: true
20
+ });
21
+
22
+ //# sourceMappingURL=prebuilt-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/const/prebuilt-components.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport LoadingModal from '../components/loading-modal'\n\nexport const LOADING_OVERLAY_ELEMENT = <LoadingModal open />\n"],"names":["LoadingModal","LOADING_OVERLAY_ELEMENT","open"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,OAAOA,kBAAkB,iCAA6B;AAEtD,OAAO,MAAMC,wCAA0B,KAACD;IAAaE,IAAI;GAAG"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { SvgIconProps } from '@mui/material';
18
+ import { type AglynLogoProps } from './aglyn-logo-class-keys';
19
+ export * from './aglyn-besigner-logo-full';
20
+ export * from './aglyn-console-logo-full';
21
+ export * from './aglyn-logo-class-keys';
22
+ export * from './aglyn-logo-full';
23
+ /**
24
+ * ## The `<title>` on every wordmark below says `Aglyn`, deliberately
25
+ *
26
+ * The brand-literal ratchet learned to read JSX text in AGL-2350 and the
27
+ * `<title>` element in each of these wordmarks — and in `aglyn-logo-full.tsx`
28
+ * beside them — is what it found. They are baselined rather than rewritten,
29
+ * and a future sweep should leave them alone.
30
+ *
31
+ * A `<title>` inside an `<svg>` is the ACCESSIBLE NAME of the artwork around
32
+ * it, and this artwork is Aglyn's own compass mark and logotype, drawn as
33
+ * vector paths. Substituting `productName` would announce a white-label org's
34
+ * name over a picture that unmistakably draws ours — the label would become
35
+ * false to the only users who ever hear it, for no gain, since a screen-reader
36
+ * user and a sighted one would then be told different things about the same
37
+ * image. It is the `docs-self-host.mjs` line: *what must not survive is a
38
+ * value the software ACTS on*, and an accessible name for a fixed drawing is
39
+ * not one.
40
+ *
41
+ * The real question is not what these say but WHERE they render.
42
+ * `main.layout.tsx` already swaps the console chrome on `whiteLabel`; the open
43
+ * item is every other placement, the tenant admin bar's `<AglynMark />` most
44
+ * of all, which sits on a white-label customer's PUBLISHED site. That is
45
+ * tracked as AGL-2350 and is a product decision, not a lint fix — no detector
46
+ * that reads source can see a wordmark anyway, because the paths carry the
47
+ * brand with no string in them at all.
48
+ */
49
+ export declare const AglynLogoMark: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme> & AglynLogoProps, {}, {}>;
50
+ export declare const AglynLogoText: import("@emotion/styled").StyledComponent<import("@mui/material").SvgIconOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").SVGProps<SVGSVGElement>, "children" | "style" | "className" | "color" | "fontSize" | "shapeRendering" | "classes" | "sx" | "htmlColor" | "inheritViewBox" | "titleAccess" | "viewBox"> & {
51
+ component?: React.ElementType | undefined;
52
+ } & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme> & AglynLogoProps, {}, {}>;
53
+ export declare const AGLYN_SVG_LOGO: {
54
+ path: string;
55
+ viewBox: string;
56
+ };
57
+ export declare const AGLYN_SVG_APP_ICON: {
58
+ path: string;
59
+ viewBox: string;
60
+ };
61
+ export declare const BESIGNER_SVG_LOGO: {
62
+ path: string;
63
+ viewBox: string;
64
+ };
65
+ export declare const AglynSvgLogo: import("react").ForwardRefExoticComponent<Omit<SvgIconProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
66
+ export declare const BesignerSvgLogo: import("react").ForwardRefExoticComponent<Omit<SvgIconProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
67
+ export interface AglynSvgIconProps extends SvgIconProps {
68
+ rectBgColor?: string;
69
+ a1Color?: string;
70
+ a2Color?: string;
71
+ a3Color?: string;
72
+ rounded?: boolean;
73
+ bordered?: boolean;
74
+ }
75
+ export declare const AglynSvgIcon: import("@emotion/styled").StyledComponent<Omit<AglynSvgIconProps, "ref"> & import("react").RefAttributes<any> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme> & AglynSvgIconProps, {}, {}>;