@aglyn/plugins-mui 1.0.0-beta.217 → 1.0.0-beta.219

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 (62) hide show
  1. package/README.md +2 -1
  2. package/package.json +9 -9
  3. package/src/lib/components/accordion.js +1 -1
  4. package/src/lib/components/accordion.js.map +1 -1
  5. package/src/lib/components/blocks.js +1 -1
  6. package/src/lib/components/blocks.js.map +1 -1
  7. package/src/lib/components/breadcrumbs.js +1 -1
  8. package/src/lib/components/breadcrumbs.js.map +1 -1
  9. package/src/lib/components/button.js +5 -5
  10. package/src/lib/components/button.js.map +1 -1
  11. package/src/lib/components/collection-categories.js +1 -1
  12. package/src/lib/components/collection-categories.js.map +1 -1
  13. package/src/lib/components/collection-entries.js +1 -1
  14. package/src/lib/components/collection-entries.js.map +1 -1
  15. package/src/lib/components/collection-entry-body.js +1 -1
  16. package/src/lib/components/collection-entry-body.js.map +1 -1
  17. package/src/lib/components/collection-search.js +1 -1
  18. package/src/lib/components/collection-search.js.map +1 -1
  19. package/src/lib/components/document-root.js +1 -1
  20. package/src/lib/components/document-root.js.map +1 -1
  21. package/src/lib/components/image.js +4 -4
  22. package/src/lib/components/image.js.map +1 -1
  23. package/src/lib/components/language-switcher.js +3 -3
  24. package/src/lib/components/language-switcher.js.map +1 -1
  25. package/src/lib/components/layout-slot.d.ts +1 -1
  26. package/src/lib/components/layout-slot.js +3 -3
  27. package/src/lib/components/layout-slot.js.map +1 -1
  28. package/src/lib/components/link-box.js +4 -4
  29. package/src/lib/components/link-box.js.map +1 -1
  30. package/src/lib/components/markdown.d.ts +3 -1
  31. package/src/lib/components/markdown.js +3 -3
  32. package/src/lib/components/markdown.js.map +1 -1
  33. package/src/lib/components/pagination.d.ts +1 -1
  34. package/src/lib/components/pagination.js +6 -2
  35. package/src/lib/components/pagination.js.map +1 -1
  36. package/src/lib/components/screen-link.js +7 -7
  37. package/src/lib/components/screen-link.js.map +1 -1
  38. package/src/lib/components/tabs.d.ts +1 -1
  39. package/src/lib/components/tabs.js +6 -2
  40. package/src/lib/components/tabs.js.map +1 -1
  41. package/src/lib/components/video.d.ts +5 -4
  42. package/src/lib/components/video.js +24 -22
  43. package/src/lib/components/video.js.map +1 -1
  44. package/src/lib/constants/field-presets.js +4 -0
  45. package/src/lib/constants/field-presets.js.map +1 -1
  46. package/src/lib/element-tier.d.ts +0 -2
  47. package/src/lib/element-tier.js +0 -2
  48. package/src/lib/element-tier.js.map +1 -1
  49. package/src/lib/plugin.js +0 -32
  50. package/src/lib/plugin.js.map +1 -1
  51. package/src/lib/video-embed-providers.d.ts +30 -0
  52. package/src/lib/video-embed-providers.js +125 -0
  53. package/src/lib/video-embed-providers.js.map +1 -0
  54. package/src/lib/components/function-controls.d.ts +0 -66
  55. package/src/lib/components/function-controls.js +0 -207
  56. package/src/lib/components/function-controls.js.map +0 -1
  57. package/src/lib/components/function-scope.d.ts +0 -110
  58. package/src/lib/components/function-scope.js +0 -478
  59. package/src/lib/components/function-scope.js.map +0 -1
  60. package/src/lib/components/function-widget.d.ts +0 -75
  61. package/src/lib/components/function-widget.js +0 -307
  62. package/src/lib/components/function-widget.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/function-controls.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 type * as Aglyn from '@aglyn/aglyn'\nimport Chip from '@mui/material/Chip'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport Stack from '@mui/material/Stack'\nimport Switch from '@mui/material/Switch'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport { useId } from 'react'\n\n/**\n * How one function parameter is ASKED (AGL-3202), shared by the Function\n * Widget, which asks every parameter in a row, and the Function Input\n * element, which asks one wherever the author put it.\n */\n\n/** The control a parameter is drawn as. `auto` follows the parameter. */\nexport type FunctionControlKind =\n | 'auto'\n | 'number'\n | 'text'\n | 'select'\n | 'chips'\n | 'switch'\n\nexport const FUNCTION_CONTROL_KINDS: readonly FunctionControlKind[] = [\n 'auto',\n 'number',\n 'text',\n 'select',\n 'chips',\n 'switch',\n]\n\n/** What each input starts with: the parameter's own default, or nothing. */\nexport function initialFunctionArguments(\n definition: Aglyn.HostFunction | undefined,\n): Record<string, string> {\n const args: Record<string, string> = {}\n for (const parameter of definition?.parameters ?? []) {\n if (parameter.defaultValue != null && parameter.defaultValue !== '') {\n args[parameter.name] = String(parameter.defaultValue)\n } else if (parameter.options?.length) {\n // A select always shows a choice, so the function has to receive the\n // one on screen — not an empty string the visitor never saw.\n args[parameter.name] = String(parameter.options[0].value)\n }\n }\n return args\n}\n\n/** A result as a visitor reads it. */\nexport function displayFunctionValue(\n value: number | string | boolean | undefined,\n): string {\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return value == null ? '' : String(value)\n}\n\n/**\n * Whether a result counts as \"yes\" for an element that shows or hides on it.\n * The strings a function is likely to have built — `'false'`, `'0'`, `'no'` —\n * read as no, because a text local is the only way a function can carry a\n * flag it computed from text.\n */\nexport function isFunctionValueTruthy(\n value: number | string | boolean | undefined,\n): boolean {\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value !== 0 && !Number.isNaN(value)\n const text = String(value ?? '').trim().toLowerCase()\n return text !== '' && text !== 'false' && text !== '0' && text !== 'no'\n}\n\n/** `control: auto` resolved against what the parameter is. */\nexport function resolveFunctionControl(\n control: FunctionControlKind | undefined,\n parameter: Pick<Aglyn.HostFunctionParameter, 'type' | 'options'> | undefined,\n hasChoices: boolean,\n): Exclude<FunctionControlKind, 'auto'> {\n if (control && control !== 'auto') return control\n if (hasChoices || parameter?.options?.length) return 'select'\n if (parameter?.type === 'boolean') return 'switch'\n if (parameter?.type === 'number') return 'number'\n return 'text'\n}\n\n/** Two values name the same choice: \"25\" and 25.0 are one quick pick. */\nfunction sameChoice(left: string, right: string): boolean {\n if (left === right) return true\n if (left.trim() === '' || right.trim() === '') return false\n const a = Number(left)\n const b = Number(right)\n return Number.isFinite(a) && Number.isFinite(b) && a === b\n}\n\nexport interface FunctionParameterControlProps {\n /** The parameter's identifier; the label when nothing better is given. */\n name: string\n type?: Aglyn.FunctionValueType\n required?: boolean\n control?: FunctionControlKind\n label?: string\n hideLabel?: boolean\n /** The choices offered by a select or a row of chips. */\n options?: Aglyn.HostFunctionParameterOption[]\n value: string\n onChange: (value: string) => void\n /** The besigner draws the control so it can be designed around; it is inert. */\n disabled?: boolean\n width?: number | string\n}\n\n/**\n * One parameter, drawn as what it is.\n *\n * - **select** is NATIVE. A portal-mounted menu is one more thing a\n * transformed or clipped ancestor can misplace, and on a phone the platform\n * picker is the better control.\n * - **chips** are quick picks: buttons that SET the value, pressed when the\n * value matches. They are how a number box gets \"10 · 25 · 50 · 100\"\n * beside it — two controls on one parameter, which is why this takes a\n * value and an onChange and holds no state of its own.\n */\nexport function FunctionParameterControl(props: FunctionParameterControlProps) {\n const {\n name,\n type,\n required,\n control,\n label,\n hideLabel,\n options = [],\n value,\n onChange,\n disabled,\n width,\n } = props\n const groupLabelId = useId()\n const text = label?.trim() || name\n const kind = resolveFunctionControl(control, { type, options }, options.length > 0)\n if (kind === 'chips') {\n return (\n <Stack spacing={0.75} role=\"group\" aria-labelledby={groupLabelId}>\n <Typography\n id={groupLabelId}\n variant=\"caption\"\n color=\"text.secondary\"\n sx={hideLabel ? visuallyHidden : { fontWeight: 500 }}\n >\n {text}\n </Typography>\n <Stack direction=\"row\" spacing={0.75} sx={{ flexWrap: 'wrap', rowGap: 0.75 }}>\n {options.map((option) => {\n const pressed = sameChoice(value, option.value)\n return (\n <Chip\n key={option.value}\n label={option.label?.trim() || option.value}\n size=\"small\"\n clickable={!disabled}\n disabled={disabled}\n color={pressed ? 'primary' : 'default'}\n variant={pressed ? 'filled' : 'outlined'}\n aria-pressed={pressed}\n onClick={() => onChange(option.value)}\n />\n )\n })}\n </Stack>\n </Stack>\n )\n }\n if (kind === 'switch') {\n return (\n <FormControlLabel\n label={text}\n disabled={disabled}\n control={\n <Switch\n checked={value === 'true'}\n onChange={(event) => onChange(event.target.checked ? 'true' : 'false')}\n />\n }\n />\n )\n }\n if (kind === 'select') {\n return (\n <TextField\n select\n label={hideLabel ? undefined : text}\n required={Boolean(required)}\n value={value}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value)}\n size=\"small\"\n slotProps={{\n select: { native: true },\n htmlInput: hideLabel ? { 'aria-label': text } : undefined,\n }}\n sx={{ minWidth: width ?? 200 }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label?.trim() || option.value}\n </option>\n ))}\n </TextField>\n )\n }\n return (\n <TextField\n label={hideLabel ? undefined : text}\n required={Boolean(required)}\n value={value}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value)}\n size=\"small\"\n type={kind === 'number' ? 'number' : undefined}\n slotProps={{\n htmlInput: {\n ...(kind === 'number' ? { inputMode: 'decimal' } : {}),\n ...(hideLabel ? { 'aria-label': text } : {}),\n },\n }}\n sx={{ width: width ?? (label ? 200 : 140) }}\n />\n )\n}\n\nconst visuallyHidden = {\n border: 0,\n clip: 'rect(0 0 0 0)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: 0,\n position: 'absolute',\n whiteSpace: 'nowrap',\n width: '1px',\n} as const\n"],"names":["Chip","FormControlLabel","Stack","Switch","TextField","Typography","useId","FUNCTION_CONTROL_KINDS","initialFunctionArguments","definition","args","parameter","parameters","defaultValue","name","String","options","length","value","displayFunctionValue","isFunctionValueTruthy","Number","isNaN","text","trim","toLowerCase","resolveFunctionControl","control","hasChoices","type","sameChoice","left","right","a","b","isFinite","FunctionParameterControl","props","required","label","hideLabel","onChange","disabled","width","groupLabelId","kind","spacing","role","aria-labelledby","id","variant","color","sx","visuallyHidden","fontWeight","direction","flexWrap","rowGap","map","option","pressed","size","clickable","aria-pressed","onClick","checked","event","target","select","undefined","Boolean","slotProps","native","htmlInput","minWidth","inputMode","border","clip","height","margin","overflow","padding","position","whiteSpace"],"mappings":"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"}
@@ -1,110 +0,0 @@
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
- import { type ReactNode } from 'react';
19
- import { type FunctionControlKind } from './function-controls';
20
- /**
21
- * A CALCULATOR AN AUTHOR LAYS OUT (AGL-3202).
22
- *
23
- * The Function Widget draws a whole calculator itself: inputs in a row, a
24
- * button, a result. That is the right block for "a quote in a sidebar" and
25
- * the wrong one for the page that prompted this — a comparison with a number
26
- * box AND quick picks on the same value, two questions asked as lists, a
27
- * table of five rows where four can be filtered away, one row highlighted, a
28
- * sentence under it and a footnote that changes with the choices. No amount
29
- * of options on one block reaches that, and it should not have to: laying
30
- * things out is what the canvas is for.
31
- *
32
- * So the pieces are separate elements, and one function binds them:
33
- *
34
- * - **Calculator** (`functionScope`) holds the function, the visitor's
35
- * answers and the live result, and is an ordinary container.
36
- * - **Calculator Input** (`functionInput`) asks ONE parameter, as a number
37
- * box, a list, a switch or a row of quick-pick chips. Two inputs may ask
38
- * the same parameter; they stay in step because the answer lives above
39
- * them.
40
- * - **Calculator Result** (`functionOutput`) shows one named value, styled
41
- * like any text.
42
- * - **Show When** (`functionShow`) is a container that appears only while a
43
- * named value is truthy — a table row a filter can remove.
44
- *
45
- * Everything between them is whatever the author builds: stacks, grids,
46
- * headings, borders. The design is theirs and the arithmetic is the site's
47
- * function, reading the site's variables.
48
- */
49
- export declare const SCOPE_ID: Aglyn.ComponentId;
50
- export declare const INPUT_ID: Aglyn.ComponentId;
51
- export declare const OUTPUT_ID: Aglyn.ComponentId;
52
- export declare const SHOW_ID: Aglyn.ComponentId;
53
- export interface FunctionScopeProps {
54
- /** Name of the site function every element inside is bound to. */
55
- functionName?: string;
56
- children?: ReactNode;
57
- /** Injected at compose (attachFunctionDefinitions); never authored. */
58
- definition?: Aglyn.HostFunction;
59
- /** The site variables the function names; injected beside `definition`. */
60
- globals?: Record<string, number | string | boolean>;
61
- }
62
- declare const FunctionScope: import("react").ForwardRefExoticComponent<FunctionScopeProps & import("react").RefAttributes<HTMLDivElement>>;
63
- export interface FunctionInputProps {
64
- /** The function parameter this control asks. */
65
- parameter?: string;
66
- control?: FunctionControlKind;
67
- /** Overrides the parameter's own label. */
68
- label?: string;
69
- hideLabel?: boolean;
70
- /**
71
- * Overrides the parameter's own choices, as `value: Label, value: Label`.
72
- * This is how quick picks are given: `10, 25, 50, 100` beside a number box.
73
- */
74
- choices?: string;
75
- }
76
- declare const FunctionInput: import("react").ForwardRefExoticComponent<FunctionInputProps & import("react").RefAttributes<HTMLDivElement>>;
77
- export interface FunctionOutputProps {
78
- /** A parameter or variable of the function; empty is its return value. */
79
- name?: string;
80
- /** What the besigner shows in the result's place, e.g. `$625`. */
81
- placeholder?: string;
82
- /** Read a change aloud. One result per calculator, usually the sentence. */
83
- announce?: boolean;
84
- element?: 'div' | 'p' | 'span';
85
- }
86
- /**
87
- * `**like this**` becomes emphasis, and nothing else is markup. The value is
88
- * text a function built — often from what a visitor typed — so it is split
89
- * into React nodes and never parsed as HTML.
90
- */
91
- export declare function renderFunctionEmphasis(text: string): ReactNode;
92
- declare const FunctionOutput: import("react").ForwardRefExoticComponent<FunctionOutputProps & import("react").RefAttributes<HTMLElement>>;
93
- export interface FunctionShowProps {
94
- /** A parameter or variable of the function. */
95
- when?: string;
96
- /** Show while the value is NOT truthy instead. */
97
- invert?: boolean;
98
- children?: ReactNode;
99
- }
100
- declare const FunctionShow: import("react").ForwardRefExoticComponent<FunctionShowProps & import("react").RefAttributes<HTMLDivElement>>;
101
- export declare const schema: Aglyn.ComponentSchema<FunctionScopeProps>;
102
- export declare const functionInputSchema: Aglyn.ComponentSchema<FunctionInputProps>;
103
- export declare const functionOutputSchema: Aglyn.ComponentSchema<FunctionOutputProps>;
104
- export declare const functionShowSchema: Aglyn.ComponentSchema<FunctionShowProps>;
105
- export declare const presets: Aglyn.PresetSchema[];
106
- export declare const functionInputPresets: Aglyn.PresetSchema[];
107
- export declare const functionOutputPresets: Aglyn.PresetSchema[];
108
- export declare const functionShowPresets: Aglyn.PresetSchema[];
109
- export { FunctionInput, FunctionOutput, FunctionShow };
110
- export default FunctionScope;
@@ -1,478 +0,0 @@
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