@aglyn/plugins-mui 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 (177) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +22 -0
  3. package/package.json +47 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +22 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/accordion.d.ts +96 -0
  8. package/src/lib/components/accordion.js +392 -0
  9. package/src/lib/components/accordion.js.map +1 -0
  10. package/src/lib/components/app-bar.d.ts +32 -0
  11. package/src/lib/components/app-bar.js +86 -0
  12. package/src/lib/components/app-bar.js.map +1 -0
  13. package/src/lib/components/blocks.d.ts +46 -0
  14. package/src/lib/components/blocks.js +1007 -0
  15. package/src/lib/components/blocks.js.map +1 -0
  16. package/src/lib/components/box.d.ts +47 -0
  17. package/src/lib/components/box.js +125 -0
  18. package/src/lib/components/box.js.map +1 -0
  19. package/src/lib/components/breadcrumbs.d.ts +44 -0
  20. package/src/lib/components/breadcrumbs.js +172 -0
  21. package/src/lib/components/breadcrumbs.js.map +1 -0
  22. package/src/lib/components/button.d.ts +89 -0
  23. package/src/lib/components/button.js +272 -0
  24. package/src/lib/components/button.js.map +1 -0
  25. package/src/lib/components/card.d.ts +61 -0
  26. package/src/lib/components/card.js +336 -0
  27. package/src/lib/components/card.js.map +1 -0
  28. package/src/lib/components/collection.d.ts +514 -0
  29. package/src/lib/components/collection.js +2999 -0
  30. package/src/lib/components/collection.js.map +1 -0
  31. package/src/lib/components/container.d.ts +42 -0
  32. package/src/lib/components/container.js +169 -0
  33. package/src/lib/components/container.js.map +1 -0
  34. package/src/lib/components/custom-html.d.ts +78 -0
  35. package/src/lib/components/custom-html.js +219 -0
  36. package/src/lib/components/custom-html.js.map +1 -0
  37. package/src/lib/components/data-table.d.ts +57 -0
  38. package/src/lib/components/data-table.js +216 -0
  39. package/src/lib/components/data-table.js.map +1 -0
  40. package/src/lib/components/document-root.d.ts +77 -0
  41. package/src/lib/components/document-root.js +118 -0
  42. package/src/lib/components/document-root.js.map +1 -0
  43. package/src/lib/components/drawer.d.ts +93 -0
  44. package/src/lib/components/drawer.js +566 -0
  45. package/src/lib/components/drawer.js.map +1 -0
  46. package/src/lib/components/function-controls.d.ts +66 -0
  47. package/src/lib/components/function-controls.js +207 -0
  48. package/src/lib/components/function-controls.js.map +1 -0
  49. package/src/lib/components/function-scope.d.ts +110 -0
  50. package/src/lib/components/function-scope.js +478 -0
  51. package/src/lib/components/function-scope.js.map +1 -0
  52. package/src/lib/components/function-widget.d.ts +75 -0
  53. package/src/lib/components/function-widget.js +307 -0
  54. package/src/lib/components/function-widget.js.map +1 -0
  55. package/src/lib/components/grid.d.ts +91 -0
  56. package/src/lib/components/grid.js +322 -0
  57. package/src/lib/components/grid.js.map +1 -0
  58. package/src/lib/components/icon.d.ts +54 -0
  59. package/src/lib/components/icon.js +163 -0
  60. package/src/lib/components/icon.js.map +1 -0
  61. package/src/lib/components/image-list.d.ts +58 -0
  62. package/src/lib/components/image-list.js +336 -0
  63. package/src/lib/components/image-list.js.map +1 -0
  64. package/src/lib/components/image.d.ts +154 -0
  65. package/src/lib/components/image.js +451 -0
  66. package/src/lib/components/image.js.map +1 -0
  67. package/src/lib/components/inline-text.d.ts +74 -0
  68. package/src/lib/components/inline-text.js +407 -0
  69. package/src/lib/components/inline-text.js.map +1 -0
  70. package/src/lib/components/language-switcher.d.ts +35 -0
  71. package/src/lib/components/language-switcher.js +179 -0
  72. package/src/lib/components/language-switcher.js.map +1 -0
  73. package/src/lib/components/layout-slot.d.ts +68 -0
  74. package/src/lib/components/layout-slot.js +192 -0
  75. package/src/lib/components/layout-slot.js.map +1 -0
  76. package/src/lib/components/link-box-accessible-name.d.ts +79 -0
  77. package/src/lib/components/link-box-accessible-name.js +158 -0
  78. package/src/lib/components/link-box-accessible-name.js.map +1 -0
  79. package/src/lib/components/link-box.d.ts +66 -0
  80. package/src/lib/components/link-box.js +212 -0
  81. package/src/lib/components/link-box.js.map +1 -0
  82. package/src/lib/components/list-item-text.d.ts +22 -0
  83. package/src/lib/components/list-item-text.js +86 -0
  84. package/src/lib/components/list-item-text.js.map +1 -0
  85. package/src/lib/components/list-item.d.ts +32 -0
  86. package/src/lib/components/list-item.js +127 -0
  87. package/src/lib/components/list-item.js.map +1 -0
  88. package/src/lib/components/list.d.ts +34 -0
  89. package/src/lib/components/list.js +108 -0
  90. package/src/lib/components/list.js.map +1 -0
  91. package/src/lib/components/markdown.d.ts +129 -0
  92. package/src/lib/components/markdown.js +853 -0
  93. package/src/lib/components/markdown.js.map +1 -0
  94. package/src/lib/components/nav-menu.d.ts +68 -0
  95. package/src/lib/components/nav-menu.js +683 -0
  96. package/src/lib/components/nav-menu.js.map +1 -0
  97. package/src/lib/components/pagination.d.ts +59 -0
  98. package/src/lib/components/pagination.js +243 -0
  99. package/src/lib/components/pagination.js.map +1 -0
  100. package/src/lib/components/paper.d.ts +47 -0
  101. package/src/lib/components/paper.js +202 -0
  102. package/src/lib/components/paper.js.map +1 -0
  103. package/src/lib/components/plugin-frame.d.ts +64 -0
  104. package/src/lib/components/plugin-frame.js +335 -0
  105. package/src/lib/components/plugin-frame.js.map +1 -0
  106. package/src/lib/components/plugin.d.ts +95 -0
  107. package/src/lib/components/plugin.js +304 -0
  108. package/src/lib/components/plugin.js.map +1 -0
  109. package/src/lib/components/product.d.ts +40 -0
  110. package/src/lib/components/product.js +287 -0
  111. package/src/lib/components/product.js.map +1 -0
  112. package/src/lib/components/reusable-instance.d.ts +57 -0
  113. package/src/lib/components/reusable-instance.js +126 -0
  114. package/src/lib/components/reusable-instance.js.map +1 -0
  115. package/src/lib/components/screen-link.d.ts +85 -0
  116. package/src/lib/components/screen-link.js +324 -0
  117. package/src/lib/components/screen-link.js.map +1 -0
  118. package/src/lib/components/search-box.d.ts +41 -0
  119. package/src/lib/components/search-box.js +125 -0
  120. package/src/lib/components/search-box.js.map +1 -0
  121. package/src/lib/components/section.d.ts +56 -0
  122. package/src/lib/components/section.js +132 -0
  123. package/src/lib/components/section.js.map +1 -0
  124. package/src/lib/components/stack.d.ts +55 -0
  125. package/src/lib/components/stack.js +309 -0
  126. package/src/lib/components/stack.js.map +1 -0
  127. package/src/lib/components/tabs.d.ts +288 -0
  128. package/src/lib/components/tabs.js +788 -0
  129. package/src/lib/components/tabs.js.map +1 -0
  130. package/src/lib/components/theme-mode-switcher.d.ts +38 -0
  131. package/src/lib/components/theme-mode-switcher.js +168 -0
  132. package/src/lib/components/theme-mode-switcher.js.map +1 -0
  133. package/src/lib/components/toolbar.d.ts +37 -0
  134. package/src/lib/components/toolbar.js +117 -0
  135. package/src/lib/components/toolbar.js.map +1 -0
  136. package/src/lib/components/typography.d.ts +33 -0
  137. package/src/lib/components/typography.js +433 -0
  138. package/src/lib/components/typography.js.map +1 -0
  139. package/src/lib/components/video-lightbox-controls.d.ts +131 -0
  140. package/src/lib/components/video-lightbox-controls.js +536 -0
  141. package/src/lib/components/video-lightbox-controls.js.map +1 -0
  142. package/src/lib/components/video-lightbox.d.ts +60 -0
  143. package/src/lib/components/video-lightbox.js +247 -0
  144. package/src/lib/components/video-lightbox.js.map +1 -0
  145. package/src/lib/components/video-playback-beacon.d.ts +80 -0
  146. package/src/lib/components/video-playback-beacon.js +128 -0
  147. package/src/lib/components/video-playback-beacon.js.map +1 -0
  148. package/src/lib/components/video-player-frame.d.ts +58 -0
  149. package/src/lib/components/video-player-frame.js +51 -0
  150. package/src/lib/components/video-player-frame.js.map +1 -0
  151. package/src/lib/components/video.d.ts +220 -0
  152. package/src/lib/components/video.js +874 -0
  153. package/src/lib/components/video.js.map +1 -0
  154. package/src/lib/constants/bundle-common.d.ts +17 -0
  155. package/src/lib/constants/bundle-common.js +18 -0
  156. package/src/lib/constants/bundle-common.js.map +1 -0
  157. package/src/lib/constants/field-presets.d.ts +93 -0
  158. package/src/lib/constants/field-presets.js +248 -0
  159. package/src/lib/constants/field-presets.js.map +1 -0
  160. package/src/lib/plugin.d.ts +80 -0
  161. package/src/lib/plugin.js +599 -0
  162. package/src/lib/plugin.js.map +1 -0
  163. package/src/lib/utils/author-html-label.d.ts +73 -0
  164. package/src/lib/utils/author-html-label.js +89 -0
  165. package/src/lib/utils/author-html-label.js.map +1 -0
  166. package/src/lib/utils/drop-cleared-props.d.ts +18 -0
  167. package/src/lib/utils/drop-cleared-props.js +74 -0
  168. package/src/lib/utils/drop-cleared-props.js.map +1 -0
  169. package/src/lib/utils/element-picker.d.ts +99 -0
  170. package/src/lib/utils/element-picker.js +140 -0
  171. package/src/lib/utils/element-picker.js.map +1 -0
  172. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  173. package/src/lib/utils/generate-preset-id.js +25 -0
  174. package/src/lib/utils/generate-preset-id.js.map +1 -0
  175. package/src/lib/utils/link-target-props.d.ts +53 -0
  176. package/src/lib/utils/link-target-props.js +53 -0
  177. package/src/lib/utils/link-target-props.js.map +1 -0
@@ -0,0 +1,478 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ /**
5
+ * @license
6
+ * Copyright 2026 Aglyn LLC
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */ import * as Aglyn from "@aglyn/aglyn";
20
+ import { mdiCalculatorVariantOutline, mdiEyeOutline, mdiFormTextbox, mdiFunctionVariant } from "@aglyn/shared-data-mdi";
21
+ import Box from "@mui/material/Box";
22
+ import { createContext, forwardRef, Fragment, useCallback, useContext, useMemo, useState } from "react";
23
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
24
+ import { generatePresetId } from "../utils/generate-preset-id.js";
25
+ import { FUNCTION_CONTROL_KINDS, FunctionParameterControl, displayFunctionValue, initialFunctionArguments, isFunctionValueTruthy } from "./function-controls.js";
26
+ /**
27
+ * A CALCULATOR AN AUTHOR LAYS OUT (AGL-3202).
28
+ *
29
+ * The Function Widget draws a whole calculator itself: inputs in a row, a
30
+ * button, a result. That is the right block for "a quote in a sidebar" and
31
+ * the wrong one for the page that prompted this — a comparison with a number
32
+ * box AND quick picks on the same value, two questions asked as lists, a
33
+ * table of five rows where four can be filtered away, one row highlighted, a
34
+ * sentence under it and a footnote that changes with the choices. No amount
35
+ * of options on one block reaches that, and it should not have to: laying
36
+ * things out is what the canvas is for.
37
+ *
38
+ * So the pieces are separate elements, and one function binds them:
39
+ *
40
+ * - **Calculator** (`functionScope`) holds the function, the visitor's
41
+ * answers and the live result, and is an ordinary container.
42
+ * - **Calculator Input** (`functionInput`) asks ONE parameter, as a number
43
+ * box, a list, a switch or a row of quick-pick chips. Two inputs may ask
44
+ * the same parameter; they stay in step because the answer lives above
45
+ * them.
46
+ * - **Calculator Result** (`functionOutput`) shows one named value, styled
47
+ * like any text.
48
+ * - **Show When** (`functionShow`) is a container that appears only while a
49
+ * named value is truthy — a table row a filter can remove.
50
+ *
51
+ * Everything between them is whatever the author builds: stacks, grids,
52
+ * headings, borders. The design is theirs and the arithmetic is the site's
53
+ * function, reading the site's variables.
54
+ */ // Component ids are persisted in screen documents; never rename.
55
+ export const SCOPE_ID = 'functionScope';
56
+ export const INPUT_ID = 'functionInput';
57
+ export const OUTPUT_ID = 'functionOutput';
58
+ export const SHOW_ID = 'functionShow';
59
+ const FunctionScopeContext = /*#__PURE__*/ createContext(null);
60
+ const FunctionScope = /*#__PURE__*/ forwardRef((props, ref)=>{
61
+ const { functionName: _functionName, children, definition, globals } = props, rest = _object_without_properties_loose(props, [
62
+ "functionName",
63
+ "children",
64
+ "definition",
65
+ "globals"
66
+ ]);
67
+ const [args, setArgs] = useState(()=>initialFunctionArguments(definition));
68
+ const setArgument = useCallback((name, value)=>{
69
+ setArgs((previous)=>_extends({}, previous, {
70
+ [name]: value
71
+ }));
72
+ }, []);
73
+ // Always live: a calculator laid out on a page has no single place a
74
+ // "Calculate" button would obviously go, and every result can be on
75
+ // screen at once. The Function Widget is the block with a button.
76
+ const run = useMemo(()=>definition ? Aglyn.evaluateHostFunction(definition, args, {
77
+ globals
78
+ }) : null, [
79
+ definition,
80
+ args,
81
+ globals
82
+ ]);
83
+ const value = useMemo(()=>({
84
+ definition,
85
+ args,
86
+ setArgument,
87
+ run
88
+ }), [
89
+ definition,
90
+ args,
91
+ setArgument,
92
+ run
93
+ ]);
94
+ return /*#__PURE__*/ _jsx(FunctionScopeContext.Provider, {
95
+ value: value,
96
+ children: /*#__PURE__*/ _jsx(Box, _extends({
97
+ ref: ref
98
+ }, rest, {
99
+ children: children
100
+ }))
101
+ });
102
+ });
103
+ FunctionScope.displayName = 'AglynFunctionScope';
104
+ const FunctionInput = /*#__PURE__*/ forwardRef((props, ref)=>{
105
+ var _ref, _ref1;
106
+ var _scope_definition_parameters, _scope_definition;
107
+ const { parameter, control, label, hideLabel, choices } = props, rest = _object_without_properties_loose(props, [
108
+ "parameter",
109
+ "control",
110
+ "label",
111
+ "hideLabel",
112
+ "choices"
113
+ ]);
114
+ const scope = useContext(FunctionScopeContext);
115
+ const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
116
+ const name = String(parameter != null ? parameter : '').trim();
117
+ const declared = scope == null ? void 0 : (_scope_definition = scope.definition) == null ? void 0 : (_scope_definition_parameters = _scope_definition.parameters) == null ? void 0 : _scope_definition_parameters.find((candidate)=>candidate.name === name);
118
+ const ownChoices = useMemo(()=>Aglyn.parseFunctionParameterOptions(choices), [
119
+ choices
120
+ ]);
121
+ const options = ownChoices.length ? ownChoices : (_ref = declared == null ? void 0 : declared.options) != null ? _ref : [];
122
+ // No function to ask on behalf of: the besigner, or a page whose function
123
+ // was deleted. In the besigner the control is still DRAWN, from its own
124
+ // attributes, so a calculator can be designed before it works. On a
125
+ // published page a control that can set nothing is residue, not a
126
+ // question, and a visitor is shown nothing.
127
+ const inert = !(scope == null ? void 0 : scope.definition) || !declared;
128
+ if (inert && !suppressNavigation) return null;
129
+ return /*#__PURE__*/ _jsx(Box, _extends({
130
+ ref: ref
131
+ }, rest, {
132
+ children: /*#__PURE__*/ _jsx(FunctionParameterControl, {
133
+ name: name || 'parameter',
134
+ type: declared == null ? void 0 : declared.type,
135
+ required: declared == null ? void 0 : declared.required,
136
+ control: control,
137
+ label: (label == null ? void 0 : label.trim()) || (declared == null ? void 0 : declared.label),
138
+ hideLabel: Boolean(hideLabel),
139
+ options: options,
140
+ value: inert ? '' : (_ref1 = scope == null ? void 0 : scope.args[name]) != null ? _ref1 : '',
141
+ onChange: (next)=>scope == null ? void 0 : scope.setArgument(name, next),
142
+ disabled: inert,
143
+ width: "100%"
144
+ })
145
+ }));
146
+ });
147
+ FunctionInput.displayName = 'AglynFunctionInput';
148
+ const OUTPUT_ELEMENTS = [
149
+ 'div',
150
+ 'p',
151
+ 'span'
152
+ ];
153
+ /**
154
+ * `**like this**` becomes emphasis, and nothing else is markup. The value is
155
+ * text a function built — often from what a visitor typed — so it is split
156
+ * into React nodes and never parsed as HTML.
157
+ */ export function renderFunctionEmphasis(text) {
158
+ const parts = text.split(/\*\*(.+?)\*\*/g);
159
+ if (parts.length === 1) return text;
160
+ return parts.map((part, index)=>index % 2 === 1 ? /*#__PURE__*/ _jsx("strong", {
161
+ children: part
162
+ }, index) : /*#__PURE__*/ _jsx(Fragment, {
163
+ children: part
164
+ }, index));
165
+ }
166
+ const FunctionOutput = /*#__PURE__*/ forwardRef((props, ref)=>{
167
+ const { name, placeholder, announce, element } = props, rest = _object_without_properties_loose(props, [
168
+ "name",
169
+ "placeholder",
170
+ "announce",
171
+ "element"
172
+ ]);
173
+ const scope = useContext(FunctionScopeContext);
174
+ const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
175
+ const key = String(name != null ? name : '').trim();
176
+ const run = scope == null ? void 0 : scope.run;
177
+ let text = '';
178
+ if (run == null ? void 0 : run.ok) {
179
+ text = displayFunctionValue(key ? run.scope[key] : run.value);
180
+ } else if (suppressNavigation || !(scope == null ? void 0 : scope.definition)) {
181
+ // Designing: show what will stand here. On a published page a missing
182
+ // function shows nothing rather than a placeholder dressed as a price.
183
+ text = suppressNavigation ? placeholder || (key ? `{${key}}` : '{result}') : '';
184
+ }
185
+ if (!text) return null;
186
+ const tag = OUTPUT_ELEMENTS.includes(element) ? element : 'div';
187
+ return /*#__PURE__*/ _jsx(Box, _extends({
188
+ ref: ref,
189
+ component: tag
190
+ }, announce ? {
191
+ 'aria-live': 'polite'
192
+ } : {}, rest, {
193
+ children: renderFunctionEmphasis(text)
194
+ }));
195
+ });
196
+ FunctionOutput.displayName = 'AglynFunctionOutput';
197
+ const FunctionShow = /*#__PURE__*/ forwardRef((props, ref)=>{
198
+ const { when, invert, children } = props, rest = _object_without_properties_loose(props, [
199
+ "when",
200
+ "invert",
201
+ "children"
202
+ ]);
203
+ const scope = useContext(FunctionScopeContext);
204
+ const key = String(when != null ? when : '').trim();
205
+ const run = scope == null ? void 0 : scope.run;
206
+ // With nothing to decide on — no function, a failed run, no name — the
207
+ // contents SHOW. Hiding is the exceptional state, and a designer has to
208
+ // be able to see the row they are laying out.
209
+ const decided = Boolean((run == null ? void 0 : run.ok) && key);
210
+ const truthy = (run == null ? void 0 : run.ok) ? isFunctionValueTruthy(run.scope[key]) : true;
211
+ if (decided && truthy === Boolean(invert)) return null;
212
+ return /*#__PURE__*/ _jsx(Box, _extends({
213
+ ref: ref
214
+ }, rest, {
215
+ children: children
216
+ }));
217
+ });
218
+ FunctionShow.displayName = 'AglynFunctionShow';
219
+ // ── Schemas ────────────────────────────────────────────────────────────────
220
+ const ICON_COLOR = '#7b1fa2';
221
+ const CONTROL_LABELS = {
222
+ auto: 'Automatic',
223
+ number: 'Number box',
224
+ text: 'Text box',
225
+ select: 'List',
226
+ chips: 'Quick picks',
227
+ switch: 'Switch'
228
+ };
229
+ export const schema = {
230
+ $id: SCOPE_ID,
231
+ pluginId: BUNDLE_ID,
232
+ displayName: 'Calculator',
233
+ description: 'A container bound to one of your functions. Put Calculator Inputs and ' + 'Calculator Results anywhere inside it and lay them out however you like.',
234
+ category: Aglyn.ComponentCategory.INPUT,
235
+ icon: {
236
+ path: mdiCalculatorVariantOutline.path,
237
+ sx: {
238
+ color: ICON_COLOR
239
+ }
240
+ },
241
+ attributes: [
242
+ {
243
+ name: 'functionName',
244
+ description: 'Name of a function from the site’s Functions card. Every input and ' + 'result inside this container reads it.',
245
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
246
+ label: 'Function name'
247
+ }
248
+ ]
249
+ };
250
+ export const functionInputSchema = {
251
+ $id: INPUT_ID,
252
+ pluginId: BUNDLE_ID,
253
+ displayName: 'Calculator Input',
254
+ description: 'Asks one parameter of the Calculator it sits in: a number box, a list, ' + 'a switch, or quick-pick chips.',
255
+ category: Aglyn.ComponentCategory.INPUT,
256
+ icon: {
257
+ path: mdiFormTextbox.path,
258
+ sx: {
259
+ color: ICON_COLOR
260
+ }
261
+ },
262
+ flags: {
263
+ selfClosing: Aglyn.FEATURE_FLAG.ENABLED
264
+ },
265
+ attributes: [
266
+ {
267
+ name: 'parameter',
268
+ description: 'The function parameter this control sets.',
269
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
270
+ label: 'Parameter'
271
+ },
272
+ {
273
+ name: 'control',
274
+ description: 'Automatic follows the parameter: a list when it has choices, a ' + 'number box for a number, a switch for a true/false. Quick picks ' + 'are buttons that set the value, for beside a number box.',
275
+ component: Aglyn.FieldComponentType.SELECT,
276
+ label: 'Ask as',
277
+ options: FUNCTION_CONTROL_KINDS.map((kind)=>({
278
+ value: kind,
279
+ label: CONTROL_LABELS[kind]
280
+ }))
281
+ },
282
+ {
283
+ name: 'choices',
284
+ description: 'The choices for a list or quick picks, as "value: Label, value: ' + 'Label" — or just "10, 25, 50, 100". Leave empty to use the ' + 'choices the function gives the parameter.',
285
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
286
+ label: 'Choices'
287
+ },
288
+ {
289
+ name: 'label',
290
+ description: 'Shown above the control instead of the parameter’s own label.',
291
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
292
+ label: 'Label'
293
+ },
294
+ {
295
+ name: 'hideLabel',
296
+ description: 'If true, the label is not drawn. It is still read to assistive ' + 'technology, so give one either way.',
297
+ component: Aglyn.FieldComponentType.SWITCH,
298
+ label: 'Hide the label?'
299
+ }
300
+ ]
301
+ };
302
+ export const functionOutputSchema = {
303
+ $id: OUTPUT_ID,
304
+ pluginId: BUNDLE_ID,
305
+ displayName: 'Calculator Result',
306
+ description: 'Shows one value from the Calculator it sits in, updated as the visitor ' + 'answers. Style it like any text.',
307
+ category: Aglyn.ComponentCategory.INPUT,
308
+ icon: {
309
+ path: mdiFunctionVariant.path,
310
+ sx: {
311
+ color: ICON_COLOR
312
+ }
313
+ },
314
+ flags: {
315
+ selfClosing: Aglyn.FEATURE_FLAG.ENABLED
316
+ },
317
+ attributes: [
318
+ {
319
+ name: 'name',
320
+ description: 'A parameter or variable of the function. Leave empty for the ' + 'function’s return value. Text the function wraps in **two ' + 'asterisks** is emphasized; nothing appears while the value is empty.',
321
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
322
+ label: 'Value'
323
+ },
324
+ {
325
+ name: 'placeholder',
326
+ description: 'What the besigner shows here, e.g. $625. Visitors never see it.',
327
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
328
+ label: 'Placeholder'
329
+ },
330
+ {
331
+ name: 'element',
332
+ description: 'The HTML element. Use span inside a line of text.',
333
+ component: Aglyn.FieldComponentType.SELECT,
334
+ label: 'Element',
335
+ options: [
336
+ {
337
+ value: 'div',
338
+ label: 'Block (div)'
339
+ },
340
+ {
341
+ value: 'p',
342
+ label: 'Paragraph (p)'
343
+ },
344
+ {
345
+ value: 'span',
346
+ label: 'Inline (span)'
347
+ }
348
+ ]
349
+ },
350
+ {
351
+ name: 'announce',
352
+ description: 'If true, a screen reader reads each change. Turn it on for one ' + 'result per calculator — usually the sentence, not every number.',
353
+ component: Aglyn.FieldComponentType.SWITCH,
354
+ label: 'Read changes aloud?'
355
+ }
356
+ ]
357
+ };
358
+ export const functionShowSchema = {
359
+ $id: SHOW_ID,
360
+ pluginId: BUNDLE_ID,
361
+ displayName: 'Show When',
362
+ description: 'A container inside a Calculator that appears only while one of the ' + 'function’s values is true, non-zero or non-empty.',
363
+ category: Aglyn.ComponentCategory.INPUT,
364
+ icon: {
365
+ path: mdiEyeOutline.path,
366
+ sx: {
367
+ color: ICON_COLOR
368
+ }
369
+ },
370
+ attributes: [
371
+ {
372
+ name: 'when',
373
+ description: 'A parameter or variable of the function. The contents show while ' + 'it is true, a number other than zero, or text that is not empty.',
374
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
375
+ label: 'Show when'
376
+ },
377
+ {
378
+ name: 'invert',
379
+ description: 'If true, the contents show while the value is NOT true.',
380
+ component: Aglyn.FieldComponentType.SWITCH,
381
+ label: 'Show when it is not?'
382
+ }
383
+ ]
384
+ };
385
+ export const presets = [
386
+ {
387
+ $id: generatePresetId(SCOPE_ID),
388
+ type: Aglyn.NodeType.PRESET,
389
+ displayName: 'Calculator',
390
+ pluginId: BUNDLE_ID,
391
+ description: 'A container bound to a function — lay out inputs and results inside',
392
+ category: Aglyn.ComponentCategory.INPUT,
393
+ icon: {
394
+ path: mdiCalculatorVariantOutline.path,
395
+ sx: {
396
+ color: ICON_COLOR
397
+ }
398
+ },
399
+ data: {
400
+ $id: null,
401
+ componentId: SCOPE_ID,
402
+ pluginId: BUNDLE_ID,
403
+ props: {}
404
+ }
405
+ }
406
+ ];
407
+ export const functionInputPresets = [
408
+ {
409
+ $id: generatePresetId(INPUT_ID),
410
+ type: Aglyn.NodeType.PRESET,
411
+ displayName: 'Calculator Input',
412
+ pluginId: BUNDLE_ID,
413
+ description: 'Asks one parameter of the Calculator it sits in',
414
+ category: Aglyn.ComponentCategory.INPUT,
415
+ icon: {
416
+ path: mdiFormTextbox.path,
417
+ sx: {
418
+ color: ICON_COLOR
419
+ }
420
+ },
421
+ data: {
422
+ $id: null,
423
+ componentId: INPUT_ID,
424
+ pluginId: BUNDLE_ID,
425
+ props: {
426
+ control: 'auto'
427
+ }
428
+ }
429
+ }
430
+ ];
431
+ export const functionOutputPresets = [
432
+ {
433
+ $id: generatePresetId(OUTPUT_ID),
434
+ type: Aglyn.NodeType.PRESET,
435
+ displayName: 'Calculator Result',
436
+ pluginId: BUNDLE_ID,
437
+ description: 'Shows one value from the Calculator it sits in',
438
+ category: Aglyn.ComponentCategory.INPUT,
439
+ icon: {
440
+ path: mdiFunctionVariant.path,
441
+ sx: {
442
+ color: ICON_COLOR
443
+ }
444
+ },
445
+ data: {
446
+ $id: null,
447
+ componentId: OUTPUT_ID,
448
+ pluginId: BUNDLE_ID,
449
+ props: {}
450
+ }
451
+ }
452
+ ];
453
+ export const functionShowPresets = [
454
+ {
455
+ $id: generatePresetId(SHOW_ID),
456
+ type: Aglyn.NodeType.PRESET,
457
+ displayName: 'Show When',
458
+ pluginId: BUNDLE_ID,
459
+ description: 'Appears only while a Calculator value is true',
460
+ category: Aglyn.ComponentCategory.INPUT,
461
+ icon: {
462
+ path: mdiEyeOutline.path,
463
+ sx: {
464
+ color: ICON_COLOR
465
+ }
466
+ },
467
+ data: {
468
+ $id: null,
469
+ componentId: SHOW_ID,
470
+ pluginId: BUNDLE_ID,
471
+ props: {}
472
+ }
473
+ }
474
+ ];
475
+ export { FunctionInput, FunctionOutput, FunctionShow };
476
+ export default FunctionScope;
477
+
478
+ //# sourceMappingURL=function-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/function-scope.tsx"],"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 * as Aglyn from '@aglyn/aglyn'\nimport {\n mdiCalculatorVariantOutline,\n mdiEyeOutline,\n mdiFormTextbox,\n mdiFunctionVariant,\n} from '@aglyn/shared-data-mdi'\nimport Box from '@mui/material/Box'\nimport {\n createContext,\n forwardRef,\n Fragment,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n FUNCTION_CONTROL_KINDS,\n FunctionParameterControl,\n displayFunctionValue,\n initialFunctionArguments,\n isFunctionValueTruthy,\n type FunctionControlKind,\n} from './function-controls'\n\n/**\n * A CALCULATOR AN AUTHOR LAYS OUT (AGL-3202).\n *\n * The Function Widget draws a whole calculator itself: inputs in a row, a\n * button, a result. That is the right block for \"a quote in a sidebar\" and\n * the wrong one for the page that prompted this — a comparison with a number\n * box AND quick picks on the same value, two questions asked as lists, a\n * table of five rows where four can be filtered away, one row highlighted, a\n * sentence under it and a footnote that changes with the choices. No amount\n * of options on one block reaches that, and it should not have to: laying\n * things out is what the canvas is for.\n *\n * So the pieces are separate elements, and one function binds them:\n *\n * - **Calculator** (`functionScope`) holds the function, the visitor's\n * answers and the live result, and is an ordinary container.\n * - **Calculator Input** (`functionInput`) asks ONE parameter, as a number\n * box, a list, a switch or a row of quick-pick chips. Two inputs may ask\n * the same parameter; they stay in step because the answer lives above\n * them.\n * - **Calculator Result** (`functionOutput`) shows one named value, styled\n * like any text.\n * - **Show When** (`functionShow`) is a container that appears only while a\n * named value is truthy — a table row a filter can remove.\n *\n * Everything between them is whatever the author builds: stacks, grids,\n * headings, borders. The design is theirs and the arithmetic is the site's\n * function, reading the site's variables.\n */\n\n// Component ids are persisted in screen documents; never rename.\nexport const SCOPE_ID: Aglyn.ComponentId = 'functionScope'\nexport const INPUT_ID: Aglyn.ComponentId = 'functionInput'\nexport const OUTPUT_ID: Aglyn.ComponentId = 'functionOutput'\nexport const SHOW_ID: Aglyn.ComponentId = 'functionShow'\n\ninterface FunctionScopeValue {\n definition?: Aglyn.HostFunction\n args: Record<string, string>\n setArgument: (name: string, value: string) => void\n run: Aglyn.FunctionRunResult | null\n}\n\nconst FunctionScopeContext = createContext<FunctionScopeValue | null>(null)\n\n// ── Calculator ─────────────────────────────────────────────────────────────\n\nexport interface FunctionScopeProps {\n /** Name of the site function every element inside is bound to. */\n functionName?: string\n children?: ReactNode\n /** Injected at compose (attachFunctionDefinitions); never authored. */\n definition?: Aglyn.HostFunction\n /** The site variables the function names; injected beside `definition`. */\n globals?: Record<string, number | string | boolean>\n}\n\nconst FunctionScope = forwardRef<HTMLDivElement, FunctionScopeProps>(\n (props, ref) => {\n const { functionName: _functionName, children, definition, globals, ...rest } = props\n const [args, setArgs] = useState<Record<string, string>>(() =>\n initialFunctionArguments(definition),\n )\n const setArgument = useCallback((name: string, value: string) => {\n setArgs((previous) => ({ ...previous, [name]: value }))\n }, [])\n // Always live: a calculator laid out on a page has no single place a\n // \"Calculate\" button would obviously go, and every result can be on\n // screen at once. The Function Widget is the block with a button.\n const run = useMemo(\n () =>\n definition\n ? Aglyn.evaluateHostFunction(definition, args, { globals })\n : null,\n [definition, args, globals],\n )\n const value = useMemo(\n () => ({ definition, args, setArgument, run }),\n [definition, args, setArgument, run],\n )\n return (\n <FunctionScopeContext.Provider value={value}>\n <Box ref={ref} {...rest}>\n {children}\n </Box>\n </FunctionScopeContext.Provider>\n )\n },\n)\nFunctionScope.displayName = 'AglynFunctionScope'\n\n// ── Calculator Input ───────────────────────────────────────────────────────\n\nexport interface FunctionInputProps {\n /** The function parameter this control asks. */\n parameter?: string\n control?: FunctionControlKind\n /** Overrides the parameter's own label. */\n label?: string\n hideLabel?: boolean\n /**\n * Overrides the parameter's own choices, as `value: Label, value: Label`.\n * This is how quick picks are given: `10, 25, 50, 100` beside a number box.\n */\n choices?: string\n}\n\nconst FunctionInput = forwardRef<HTMLDivElement, FunctionInputProps>(\n (props, ref) => {\n const { parameter, control, label, hideLabel, choices, ...rest } = props\n const scope = useContext(FunctionScopeContext)\n const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext)\n const name = String(parameter ?? '').trim()\n const declared = scope?.definition?.parameters?.find(\n (candidate) => candidate.name === name,\n )\n const ownChoices = useMemo(\n () => Aglyn.parseFunctionParameterOptions(choices),\n [choices],\n )\n const options = ownChoices.length ? ownChoices : (declared?.options ?? [])\n // No function to ask on behalf of: the besigner, or a page whose function\n // was deleted. In the besigner the control is still DRAWN, from its own\n // attributes, so a calculator can be designed before it works. On a\n // published page a control that can set nothing is residue, not a\n // question, and a visitor is shown nothing.\n const inert = !scope?.definition || !declared\n if (inert && !suppressNavigation) return null\n return (\n <Box ref={ref} {...rest}>\n <FunctionParameterControl\n name={name || 'parameter'}\n type={declared?.type}\n required={declared?.required}\n control={control}\n label={label?.trim() || declared?.label}\n hideLabel={Boolean(hideLabel)}\n options={options}\n value={inert ? '' : (scope?.args[name] ?? '')}\n onChange={(next) => scope?.setArgument(name, next)}\n disabled={inert}\n width=\"100%\"\n />\n </Box>\n )\n },\n)\nFunctionInput.displayName = 'AglynFunctionInput'\n\n// ── Calculator Result ──────────────────────────────────────────────────────\n\nexport interface FunctionOutputProps {\n /** A parameter or variable of the function; empty is its return value. */\n name?: string\n /** What the besigner shows in the result's place, e.g. `$625`. */\n placeholder?: string\n /** Read a change aloud. One result per calculator, usually the sentence. */\n announce?: boolean\n element?: 'div' | 'p' | 'span'\n}\n\nconst OUTPUT_ELEMENTS = ['div', 'p', 'span'] as const\n\n/**\n * `**like this**` becomes emphasis, and nothing else is markup. The value is\n * text a function built — often from what a visitor typed — so it is split\n * into React nodes and never parsed as HTML.\n */\nexport function renderFunctionEmphasis(text: string): ReactNode {\n const parts = text.split(/\\*\\*(.+?)\\*\\*/g)\n if (parts.length === 1) return text\n return parts.map((part, index) =>\n index % 2 === 1 ? (\n <strong key={index}>{part}</strong>\n ) : (\n <Fragment key={index}>{part}</Fragment>\n ),\n )\n}\n\nconst FunctionOutput = forwardRef<HTMLElement, FunctionOutputProps>(\n (props, ref) => {\n const { name, placeholder, announce, element, ...rest } = props\n const scope = useContext(FunctionScopeContext)\n const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext)\n const key = String(name ?? '').trim()\n const run = scope?.run\n let text = ''\n if (run?.ok) {\n text = displayFunctionValue(key ? run.scope[key] : run.value)\n } else if (suppressNavigation || !scope?.definition) {\n // Designing: show what will stand here. On a published page a missing\n // function shows nothing rather than a placeholder dressed as a price.\n text = suppressNavigation ? placeholder || (key ? `{${key}}` : '{result}') : ''\n }\n if (!text) return null\n const tag = OUTPUT_ELEMENTS.includes(element as (typeof OUTPUT_ELEMENTS)[number])\n ? element\n : 'div'\n return (\n <Box\n ref={ref}\n component={tag}\n {...(announce ? { 'aria-live': 'polite' as const } : {})}\n {...rest}\n >\n {renderFunctionEmphasis(text)}\n </Box>\n )\n },\n)\nFunctionOutput.displayName = 'AglynFunctionOutput'\n\n// ── Show When ──────────────────────────────────────────────────────────────\n\nexport interface FunctionShowProps {\n /** A parameter or variable of the function. */\n when?: string\n /** Show while the value is NOT truthy instead. */\n invert?: boolean\n children?: ReactNode\n}\n\nconst FunctionShow = forwardRef<HTMLDivElement, FunctionShowProps>(\n (props, ref) => {\n const { when, invert, children, ...rest } = props\n const scope = useContext(FunctionScopeContext)\n const key = String(when ?? '').trim()\n const run = scope?.run\n // With nothing to decide on — no function, a failed run, no name — the\n // contents SHOW. Hiding is the exceptional state, and a designer has to\n // be able to see the row they are laying out.\n const decided = Boolean(run?.ok && key)\n const truthy = run?.ok ? isFunctionValueTruthy(run.scope[key]) : true\n if (decided && truthy === Boolean(invert)) return null\n return (\n <Box ref={ref} {...rest}>\n {children}\n </Box>\n )\n },\n)\nFunctionShow.displayName = 'AglynFunctionShow'\n\n// ── Schemas ────────────────────────────────────────────────────────────────\n\nconst ICON_COLOR = '#7b1fa2'\n\nconst CONTROL_LABELS: Record<FunctionControlKind, string> = {\n auto: 'Automatic',\n number: 'Number box',\n text: 'Text box',\n select: 'List',\n chips: 'Quick picks',\n switch: 'Switch',\n}\n\nexport const schema: Aglyn.ComponentSchema<FunctionScopeProps> = {\n $id: SCOPE_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Calculator',\n description:\n 'A container bound to one of your functions. Put Calculator Inputs and ' +\n 'Calculator Results anywhere inside it and lay them out however you like.',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiCalculatorVariantOutline.path, sx: { color: ICON_COLOR } },\n attributes: [\n {\n name: 'functionName',\n description:\n 'Name of a function from the site’s Functions card. Every input and ' +\n 'result inside this container reads it.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Function name',\n },\n ],\n}\n\nexport const functionInputSchema: Aglyn.ComponentSchema<FunctionInputProps> = {\n $id: INPUT_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Calculator Input',\n description:\n 'Asks one parameter of the Calculator it sits in: a number box, a list, ' +\n 'a switch, or quick-pick chips.',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiFormTextbox.path, sx: { color: ICON_COLOR } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'parameter',\n description: 'The function parameter this control sets.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Parameter',\n },\n {\n name: 'control',\n description:\n 'Automatic follows the parameter: a list when it has choices, a ' +\n 'number box for a number, a switch for a true/false. Quick picks ' +\n 'are buttons that set the value, for beside a number box.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Ask as',\n options: FUNCTION_CONTROL_KINDS.map((kind) => ({\n value: kind,\n label: CONTROL_LABELS[kind],\n })),\n },\n {\n name: 'choices',\n description:\n 'The choices for a list or quick picks, as \"value: Label, value: ' +\n 'Label\" — or just \"10, 25, 50, 100\". Leave empty to use the ' +\n 'choices the function gives the parameter.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Choices',\n },\n {\n name: 'label',\n description: 'Shown above the control instead of the parameter’s own label.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Label',\n },\n {\n name: 'hideLabel',\n description:\n 'If true, the label is not drawn. It is still read to assistive ' +\n 'technology, so give one either way.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Hide the label?',\n },\n ],\n}\n\nexport const functionOutputSchema: Aglyn.ComponentSchema<FunctionOutputProps> = {\n $id: OUTPUT_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Calculator Result',\n description:\n 'Shows one value from the Calculator it sits in, updated as the visitor ' +\n 'answers. Style it like any text.',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiFunctionVariant.path, sx: { color: ICON_COLOR } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'name',\n description:\n 'A parameter or variable of the function. Leave empty for the ' +\n 'function’s return value. Text the function wraps in **two ' +\n 'asterisks** is emphasized; nothing appears while the value is empty.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Value',\n },\n {\n name: 'placeholder',\n description: 'What the besigner shows here, e.g. $625. Visitors never see it.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Placeholder',\n },\n {\n name: 'element',\n description: 'The HTML element. Use span inside a line of text.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Element',\n options: [\n { value: 'div', label: 'Block (div)' },\n { value: 'p', label: 'Paragraph (p)' },\n { value: 'span', label: 'Inline (span)' },\n ],\n },\n {\n name: 'announce',\n description:\n 'If true, a screen reader reads each change. Turn it on for one ' +\n 'result per calculator — usually the sentence, not every number.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Read changes aloud?',\n },\n ],\n}\n\nexport const functionShowSchema: Aglyn.ComponentSchema<FunctionShowProps> = {\n $id: SHOW_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Show When',\n description:\n 'A container inside a Calculator that appears only while one of the ' +\n 'function’s values is true, non-zero or non-empty.',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiEyeOutline.path, sx: { color: ICON_COLOR } },\n attributes: [\n {\n name: 'when',\n description:\n 'A parameter or variable of the function. The contents show while ' +\n 'it is true, a number other than zero, or text that is not empty.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Show when',\n },\n {\n name: 'invert',\n description: 'If true, the contents show while the value is NOT true.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Show when it is not?',\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(SCOPE_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Calculator',\n pluginId: BUNDLE_ID,\n description: 'A container bound to a function — lay out inputs and results inside',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiCalculatorVariantOutline.path, sx: { color: ICON_COLOR } },\n data: { $id: null, componentId: SCOPE_ID, pluginId: BUNDLE_ID, props: {} },\n },\n]\n\nexport const functionInputPresets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(INPUT_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Calculator Input',\n pluginId: BUNDLE_ID,\n description: 'Asks one parameter of the Calculator it sits in',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiFormTextbox.path, sx: { color: ICON_COLOR } },\n data: { $id: null, componentId: INPUT_ID, pluginId: BUNDLE_ID, props: { control: 'auto' } },\n },\n]\n\nexport const functionOutputPresets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(OUTPUT_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Calculator Result',\n pluginId: BUNDLE_ID,\n description: 'Shows one value from the Calculator it sits in',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiFunctionVariant.path, sx: { color: ICON_COLOR } },\n data: { $id: null, componentId: OUTPUT_ID, pluginId: BUNDLE_ID, props: {} },\n },\n]\n\nexport const functionShowPresets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(SHOW_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Show When',\n pluginId: BUNDLE_ID,\n description: 'Appears only while a Calculator value is true',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiEyeOutline.path, sx: { color: ICON_COLOR } },\n data: { $id: null, componentId: SHOW_ID, pluginId: BUNDLE_ID, props: {} },\n },\n]\n\nexport { FunctionInput, FunctionOutput, FunctionShow }\nexport default FunctionScope\n"],"names":["Aglyn","mdiCalculatorVariantOutline","mdiEyeOutline","mdiFormTextbox","mdiFunctionVariant","Box","createContext","forwardRef","Fragment","useCallback","useContext","useMemo","useState","BUNDLE_ID","generatePresetId","FUNCTION_CONTROL_KINDS","FunctionParameterControl","displayFunctionValue","initialFunctionArguments","isFunctionValueTruthy","SCOPE_ID","INPUT_ID","OUTPUT_ID","SHOW_ID","FunctionScopeContext","FunctionScope","props","ref","functionName","_functionName","children","definition","globals","rest","args","setArgs","setArgument","name","value","previous","run","evaluateHostFunction","Provider","displayName","FunctionInput","scope","parameter","control","label","hideLabel","choices","suppressNavigation","ScreenLinkContext","String","trim","declared","parameters","find","candidate","ownChoices","parseFunctionParameterOptions","options","length","inert","type","required","Boolean","onChange","next","disabled","width","OUTPUT_ELEMENTS","renderFunctionEmphasis","text","parts","split","map","part","index","strong","FunctionOutput","placeholder","announce","element","key","ok","tag","includes","component","FunctionShow","when","invert","decided","truthy","ICON_COLOR","CONTROL_LABELS","auto","number","select","chips","switch","schema","$id","pluginId","description","category","ComponentCategory","INPUT","icon","path","sx","color","attributes","FieldComponentType","TEXT_FIELD","functionInputSchema","flags","selfClosing","FEATURE_FLAG","ENABLED","SELECT","kind","SWITCH","functionOutputSchema","functionShowSchema","presets","NodeType","PRESET","data","componentId","functionInputPresets","functionOutputPresets","functionShowPresets"],"mappings":"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"}
@@ -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 * as Aglyn from '@aglyn/aglyn';
18
+ export declare const ID: Aglyn.ComponentId;
19
+ export interface FunctionWidgetProps {
20
+ /** Name of the host function to run (Functions card on the dashboard). */
21
+ functionName?: string;
22
+ title?: string;
23
+ buttonLabel?: string;
24
+ resultLabel?: string;
25
+ /**
26
+ * Several named results instead of one (AGL-3202): one per line, as
27
+ * `name | Label`, where the name is a parameter or variable of the
28
+ * function. Empty shows the return value alone, as it always has.
29
+ */
30
+ outputs?: string;
31
+ /** Recompute as the visitor types; no button (AGL-3202). */
32
+ autoRun?: boolean;
33
+ /**
34
+ * Injected at tenant compose time (attachFunctionDefinitions) — never
35
+ * authored directly. Editor canvas renders without it (inert preview).
36
+ */
37
+ definition?: Aglyn.HostFunction;
38
+ /**
39
+ * The site variables this function reads, by name (AGL-3202). Injected
40
+ * beside `definition`, and only the ones its expressions name.
41
+ */
42
+ globals?: Record<string, number | string | boolean>;
43
+ }
44
+ /** One row of the `outputs` attribute. */
45
+ export interface FunctionWidgetOutput {
46
+ name: string;
47
+ label: string;
48
+ }
49
+ /**
50
+ * `name | Label` per line. A line with no bar labels the row with the name,
51
+ * and a name may appear once: the second copy of a row is a typo, not a
52
+ * second result.
53
+ */
54
+ export declare function parseFunctionWidgetOutputs(text: string | undefined): FunctionWidgetOutput[];
55
+ /**
56
+ * Interactive function widget (Component Builder wiring, AGL-93): renders
57
+ * an input per function parameter and runs the host function client-side
58
+ * through the shared safe evaluator — a no-code calculator/logic block
59
+ * (quote estimators, eligibility checks, counters). The definition is
60
+ * injected server-side at compose; in the besigner the widget shows a
61
+ * static preview.
62
+ *
63
+ * WHAT A REAL CALCULATOR NEEDED (AGL-3202). The first one built on this
64
+ * compared five platforms, and the widget could ask for nothing but free
65
+ * text, labeled with the parameter's identifier, and could answer with
66
+ * nothing but one line. So a parameter now renders as what it IS — a number
67
+ * box, a yes/no switch, a choice list — under the label its author wrote;
68
+ * `outputs` lists several named results; and `autoRun` recomputes as the
69
+ * visitor types. All three are opt-in: a widget that sets none of them
70
+ * renders and behaves exactly as it did.
71
+ */
72
+ declare const FunctionWidget: import("react").ForwardRefExoticComponent<FunctionWidgetProps & import("react").RefAttributes<HTMLDivElement>>;
73
+ export declare const schema: Aglyn.ComponentSchema<FunctionWidgetProps>;
74
+ export declare const presets: Aglyn.PresetSchema[];
75
+ export default FunctionWidget;