@aglyn/shared-ui-jsx-forms 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 (150) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +52 -0
  4. package/src/index.d.ts +17 -0
  5. package/src/index.js +18 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/color-picker-tokens.d.ts +135 -0
  8. package/src/lib/components/color-picker-tokens.js +431 -0
  9. package/src/lib/components/color-picker-tokens.js.map +1 -0
  10. package/src/lib/components/color-picker.component.d.ts +64 -0
  11. package/src/lib/components/color-picker.component.js +322 -0
  12. package/src/lib/components/color-picker.component.js.map +1 -0
  13. package/src/lib/components/create-artifact-drawer.component.d.ts +100 -0
  14. package/src/lib/components/create-artifact-drawer.component.js +184 -0
  15. package/src/lib/components/create-artifact-drawer.component.js.map +1 -0
  16. package/src/lib/components/grid-form-template.component.d.ts +21 -0
  17. package/src/lib/components/grid-form-template.component.js +81 -0
  18. package/src/lib/components/grid-form-template.component.js.map +1 -0
  19. package/src/lib/components/icon-select.component.d.ts +52 -0
  20. package/src/lib/components/icon-select.component.js +453 -0
  21. package/src/lib/components/icon-select.component.js.map +1 -0
  22. package/src/lib/components/select.component.d.ts +58 -0
  23. package/src/lib/components/select.component.js +107 -0
  24. package/src/lib/components/select.component.js.map +1 -0
  25. package/src/lib/components/switch.component.d.ts +38 -0
  26. package/src/lib/components/switch.component.js +76 -0
  27. package/src/lib/components/switch.component.js.map +1 -0
  28. package/src/lib/components/text-field.component.d.ts +45 -0
  29. package/src/lib/components/text-field.component.js +77 -0
  30. package/src/lib/components/text-field.component.js.map +1 -0
  31. package/src/lib/components/textarea.component.d.ts +45 -0
  32. package/src/lib/components/textarea.component.js +61 -0
  33. package/src/lib/components/textarea.component.js.map +1 -0
  34. package/src/lib/components/toggle-button.component.d.ts +27 -0
  35. package/src/lib/components/toggle-button.component.js +116 -0
  36. package/src/lib/components/toggle-button.component.js.map +1 -0
  37. package/src/lib/constants/component-mappers.d.ts +42 -0
  38. package/src/lib/constants/component-mappers.js +70 -0
  39. package/src/lib/constants/component-mappers.js.map +1 -0
  40. package/src/lib/constants/dynamic-fields.d.ts +45 -0
  41. package/src/lib/constants/dynamic-fields.js +65 -0
  42. package/src/lib/constants/dynamic-fields.js.map +1 -0
  43. package/src/lib/constants/field-configurations.d.ts +53 -0
  44. package/src/lib/constants/field-configurations.js +121 -0
  45. package/src/lib/constants/field-configurations.js.map +1 -0
  46. package/src/lib/constants/flags.d.ts +72 -0
  47. package/src/lib/constants/flags.js +69 -0
  48. package/src/lib/constants/flags.js.map +1 -0
  49. package/src/lib/hocs/with-grid-item.d.ts +25 -0
  50. package/src/lib/hocs/with-grid-item.js +48 -0
  51. package/src/lib/hocs/with-grid-item.js.map +1 -0
  52. package/src/lib/jsx-forms.d.ts +41 -0
  53. package/src/lib/jsx-forms.js +42 -0
  54. package/src/lib/jsx-forms.js.map +1 -0
  55. package/src/lib/mapper/breakpoint-span.d.ts +73 -0
  56. package/src/lib/mapper/breakpoint-span.js +346 -0
  57. package/src/lib/mapper/breakpoint-span.js.map +1 -0
  58. package/src/lib/mapper/checkbox.d.ts +43 -0
  59. package/src/lib/mapper/checkbox.js +111 -0
  60. package/src/lib/mapper/checkbox.js.map +1 -0
  61. package/src/lib/mapper/css-border.d.ts +113 -0
  62. package/src/lib/mapper/css-border.js +410 -0
  63. package/src/lib/mapper/css-border.js.map +1 -0
  64. package/src/lib/mapper/css-dimension.d.ts +89 -0
  65. package/src/lib/mapper/css-dimension.js +327 -0
  66. package/src/lib/mapper/css-dimension.js.map +1 -0
  67. package/src/lib/mapper/css-gradient.d.ts +110 -0
  68. package/src/lib/mapper/css-gradient.js +720 -0
  69. package/src/lib/mapper/css-gradient.js.map +1 -0
  70. package/src/lib/mapper/data-table.d.ts +23 -0
  71. package/src/lib/mapper/data-table.js +296 -0
  72. package/src/lib/mapper/data-table.js.map +1 -0
  73. package/src/lib/mapper/date-picker.d.ts +26 -0
  74. package/src/lib/mapper/date-picker.js +69 -0
  75. package/src/lib/mapper/date-picker.js.map +1 -0
  76. package/src/lib/mapper/dual-list-select.d.ts +115 -0
  77. package/src/lib/mapper/dual-list-select.js +353 -0
  78. package/src/lib/mapper/dual-list-select.js.map +1 -0
  79. package/src/lib/mapper/field-array.d.ts +71 -0
  80. package/src/lib/mapper/field-array.js +326 -0
  81. package/src/lib/mapper/field-array.js.map +1 -0
  82. package/src/lib/mapper/form-field-grid.d.ts +155 -0
  83. package/src/lib/mapper/form-field-grid.js +194 -0
  84. package/src/lib/mapper/form-field-grid.js.map +1 -0
  85. package/src/lib/mapper/index.d.ts +50 -0
  86. package/src/lib/mapper/index.js +49 -0
  87. package/src/lib/mapper/index.js.map +1 -0
  88. package/src/lib/mapper/multiple-choice-list.d.ts +32 -0
  89. package/src/lib/mapper/multiple-choice-list.js +105 -0
  90. package/src/lib/mapper/multiple-choice-list.js.map +1 -0
  91. package/src/lib/mapper/plain-text.d.ts +31 -0
  92. package/src/lib/mapper/plain-text.js +48 -0
  93. package/src/lib/mapper/plain-text.js.map +1 -0
  94. package/src/lib/mapper/preset-choice.d.ts +106 -0
  95. package/src/lib/mapper/preset-choice.js +267 -0
  96. package/src/lib/mapper/preset-choice.js.map +1 -0
  97. package/src/lib/mapper/radio.d.ts +40 -0
  98. package/src/lib/mapper/radio.js +122 -0
  99. package/src/lib/mapper/radio.js.map +1 -0
  100. package/src/lib/mapper/select.d.ts +60 -0
  101. package/src/lib/mapper/select.js +203 -0
  102. package/src/lib/mapper/select.js.map +1 -0
  103. package/src/lib/mapper/slider.d.ts +45 -0
  104. package/src/lib/mapper/slider.js +119 -0
  105. package/src/lib/mapper/slider.js.map +1 -0
  106. package/src/lib/mapper/stored-field-value.d.ts +23 -0
  107. package/src/lib/mapper/stored-field-value.js +29 -0
  108. package/src/lib/mapper/stored-field-value.js.map +1 -0
  109. package/src/lib/mapper/sub-form.d.ts +39 -0
  110. package/src/lib/mapper/sub-form.js +108 -0
  111. package/src/lib/mapper/sub-form.js.map +1 -0
  112. package/src/lib/mapper/switch.d.ts +47 -0
  113. package/src/lib/mapper/switch.js +93 -0
  114. package/src/lib/mapper/switch.js.map +1 -0
  115. package/src/lib/mapper/tabs.d.ts +34 -0
  116. package/src/lib/mapper/tabs.js +64 -0
  117. package/src/lib/mapper/tabs.js.map +1 -0
  118. package/src/lib/mapper/text-field.d.ts +33 -0
  119. package/src/lib/mapper/text-field.js +88 -0
  120. package/src/lib/mapper/text-field.js.map +1 -0
  121. package/src/lib/mapper/textarea.d.ts +31 -0
  122. package/src/lib/mapper/textarea.js +68 -0
  123. package/src/lib/mapper/textarea.js.map +1 -0
  124. package/src/lib/mapper/theme-scale.d.ts +79 -0
  125. package/src/lib/mapper/theme-scale.js +162 -0
  126. package/src/lib/mapper/theme-scale.js.map +1 -0
  127. package/src/lib/mapper/time-picker.d.ts +26 -0
  128. package/src/lib/mapper/time-picker.js +69 -0
  129. package/src/lib/mapper/time-picker.js.map +1 -0
  130. package/src/lib/mapper/types.d.ts +43 -0
  131. package/src/lib/mapper/types.js +22 -0
  132. package/src/lib/mapper/types.js.map +1 -0
  133. package/src/lib/mapper/validation-error.d.ts +24 -0
  134. package/src/lib/mapper/validation-error.js +24 -0
  135. package/src/lib/mapper/validation-error.js.map +1 -0
  136. package/src/lib/mapper/wizard.d.ts +21 -0
  137. package/src/lib/mapper/wizard.js +203 -0
  138. package/src/lib/mapper/wizard.js.map +1 -0
  139. package/src/lib/types.d.ts +19 -0
  140. package/src/lib/types.js +18 -0
  141. package/src/lib/types.js.map +1 -0
  142. package/src/lib/utils/option-is-equal-to-value.d.ts +20 -0
  143. package/src/lib/utils/option-is-equal-to-value.js +21 -0
  144. package/src/lib/utils/option-is-equal-to-value.js.map +1 -0
  145. package/src/lib/utils/validation-message.d.ts +22 -0
  146. package/src/lib/utils/validation-message.js +24 -0
  147. package/src/lib/utils/validation-message.js.map +1 -0
  148. package/src/lib/vendor/data-driven-forms.d.ts +33 -0
  149. package/src/lib/vendor/data-driven-forms.js +29 -0
  150. package/src/lib/vendor/data-driven-forms.js.map +1 -0
@@ -0,0 +1,346 @@
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, jsxs as _jsxs } 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 { buildBreakpointSpan, parseBreakpointSpan, SPAN_BREAKPOINTS } from "@aglyn/shared-data-enums";
20
+ import { Box, Button, FormHelperText, FormLabel, MenuItem, Select, TextField as MuiTextField, Typography } from "@mui/material";
21
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
22
+ import { useFieldApi } from "../vendor/data-driven-forms.js";
23
+ import FormFieldGrid from "./form-field-grid.js";
24
+ import { validationError } from "./validation-error.js";
25
+ const emptyValues = ()=>SPAN_BREAKPOINTS.reduce((acc, key)=>{
26
+ acc[key] = '';
27
+ return acc;
28
+ }, {});
29
+ /** `''` is the only "unset"; `'0'` is a real offset an author can mean. */ const isSet = (value)=>value !== '' && value !== undefined && value !== null;
30
+ export const seedSpanDraft = (value)=>{
31
+ const parsed = parseBreakpointSpan(value);
32
+ if (parsed.raw !== undefined) {
33
+ return {
34
+ custom: true,
35
+ text: parsed.raw,
36
+ base: '',
37
+ values: emptyValues()
38
+ };
39
+ }
40
+ const values = emptyValues();
41
+ for (const key of SPAN_BREAKPOINTS){
42
+ var _parsed_values;
43
+ const span = (_parsed_values = parsed.values) == null ? void 0 : _parsed_values[key];
44
+ if (span !== undefined) values[key] = `${span}`;
45
+ }
46
+ return {
47
+ custom: false,
48
+ text: '',
49
+ base: parsed.base === undefined ? '' : `${parsed.base}`,
50
+ values
51
+ };
52
+ };
53
+ /** `'auto'`/`'grow'` stay keywords; everything else is a number. */ const toSpanValue = (option)=>option === 'auto' || option === 'grow' ? option : Number(option);
54
+ export const serializeSpanDraft = (draft)=>{
55
+ if (draft.custom) return draft.text;
56
+ if (isSet(draft.base)) return buildBreakpointSpan({
57
+ base: toSpanValue(draft.base)
58
+ });
59
+ const values = {};
60
+ for (const key of SPAN_BREAKPOINTS){
61
+ const option = draft.values[key];
62
+ if (isSet(option)) values[key] = toSpanValue(option);
63
+ }
64
+ return Object.keys(values).length ? buildBreakpointSpan({
65
+ values
66
+ }) : '';
67
+ };
68
+ /** Human labels for the cells, in the order they are rendered. */ const CELL_LABELS = {
69
+ base: 'All',
70
+ xs: 'xs',
71
+ sm: 'sm',
72
+ md: 'md',
73
+ lg: 'lg',
74
+ xl: 'xl'
75
+ };
76
+ export const BreakpointSpanField = (props)=>{
77
+ const _useFieldApi = useFieldApi(props), { input, isReadOnly, isDisabled, isRequired, label, placeholder, helperText, description, validateOnMount, meta, help, allowGrow = true, minSpan = 1, maxSpan = 12, FormFieldGridProps = {}, // Leftovers from the attribute schema this field was authored with as a
78
+ // TEXT_FIELD; they must never reach the DOM.
79
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
80
+ inputProps: _inputProps, // eslint-disable-next-line @typescript-eslint/no-unused-vars
81
+ InputProps: _InputProps, // eslint-disable-next-line @typescript-eslint/no-unused-vars
82
+ multiline: _multiline, // eslint-disable-next-line @typescript-eslint/no-unused-vars
83
+ type: _type, // eslint-disable-next-line @typescript-eslint/no-unused-vars
84
+ component: _component, // eslint-disable-next-line @typescript-eslint/no-unused-vars
85
+ tokenOptions: _tokenOptions, // eslint-disable-next-line @typescript-eslint/no-unused-vars
86
+ tokenLabelContext: _tokenLabelContext } = _useFieldApi, rest = _object_without_properties_loose(_useFieldApi, [
87
+ "input",
88
+ "isReadOnly",
89
+ "isDisabled",
90
+ "isRequired",
91
+ "label",
92
+ "placeholder",
93
+ "helperText",
94
+ "description",
95
+ "validateOnMount",
96
+ "meta",
97
+ "help",
98
+ "allowGrow",
99
+ "minSpan",
100
+ "maxSpan",
101
+ "FormFieldGridProps",
102
+ "inputProps",
103
+ "InputProps",
104
+ "multiline",
105
+ "type",
106
+ "component",
107
+ "tokenOptions",
108
+ "tokenLabelContext"
109
+ ]);
110
+ const invalid = validationError(meta, validateOnMount);
111
+ // A value persisted as a bare NUMBER (`size: 6`) is still a value the
112
+ // author has to see; reading only strings would blank the row and then
113
+ // overwrite the number on the first edit.
114
+ const value = input.value === undefined || input.value === null ? '' : `${input.value}`;
115
+ const [draft, setDraft] = useState(()=>seedSpanDraft(value));
116
+ // Re-seed only when the value changed OUTSIDE this field (a different node
117
+ // selected, an undo). Re-seeding from our own emits would fight the
118
+ // author's half-finished text in custom mode.
119
+ const emittedRef = useRef(value);
120
+ useEffect(()=>{
121
+ if (value === emittedRef.current) return;
122
+ emittedRef.current = value;
123
+ setDraft(seedSpanDraft(value));
124
+ }, [
125
+ value
126
+ ]);
127
+ const commit = useCallback((next)=>{
128
+ const serialized = serializeSpanDraft(next);
129
+ emittedRef.current = serialized;
130
+ // Text the author edited back into a modellable span gets the
131
+ // structured controls back immediately, so the mode stays DERIVED from
132
+ // the value rather than remembered in a flag that can go stale.
133
+ const reparsed = parseBreakpointSpan(serialized);
134
+ setDraft(next.custom && serialized.trim() !== '' && reparsed.raw === undefined ? seedSpanDraft(serialized) : next);
135
+ input.onChange(serialized);
136
+ }, [
137
+ input
138
+ ]);
139
+ const anyBreakpointSet = SPAN_BREAKPOINTS.some((key)=>isSet(draft.values[key]));
140
+ const baseSet = isSet(draft.base);
141
+ const locked = isDisabled || isReadOnly;
142
+ /**
143
+ * The options a cell offers. A stored value the list does not carry — a
144
+ * span wider than `maxSpan` because the container overrode `columns` — is
145
+ * appended rather than dropped, so selecting nothing else cannot silently
146
+ * rewrite it.
147
+ */ const optionsFor = useCallback((current)=>{
148
+ const options = [
149
+ 'auto'
150
+ ];
151
+ if (allowGrow) options.push('grow');
152
+ for(let span = minSpan; span <= maxSpan; span += 1){
153
+ options.push(`${span}`);
154
+ }
155
+ if (isSet(current) && !options.includes(current)) options.push(current);
156
+ return options;
157
+ }, [
158
+ allowGrow,
159
+ maxSpan,
160
+ minSpan
161
+ ]);
162
+ const cells = useMemo(()=>[
163
+ {
164
+ key: 'base',
165
+ label: CELL_LABELS.base
166
+ },
167
+ ...SPAN_BREAKPOINTS.map((key)=>({
168
+ key,
169
+ label: CELL_LABELS[key]
170
+ }))
171
+ ], []);
172
+ const handleCellChange = useCallback((key, option)=>{
173
+ if (key === 'base') {
174
+ commit(_extends({}, draft, {
175
+ base: option
176
+ }));
177
+ return;
178
+ }
179
+ commit(_extends({}, draft, {
180
+ values: _extends({}, draft.values, {
181
+ [key]: option
182
+ })
183
+ }));
184
+ }, [
185
+ commit,
186
+ draft
187
+ ]);
188
+ const handleTextChange = useCallback((event)=>{
189
+ commit(_extends({}, draft, {
190
+ custom: true,
191
+ text: event.target.value
192
+ }));
193
+ }, [
194
+ commit,
195
+ draft
196
+ ]);
197
+ const toggleCustom = useCallback(()=>{
198
+ if (draft.custom) {
199
+ // Back to the controls, seeded from whatever the text now says. Text
200
+ // the controls cannot model keeps the text box (seedSpanDraft returns
201
+ // custom), which is the honest answer rather than a silent wipe.
202
+ setDraft(seedSpanDraft(draft.text));
203
+ return;
204
+ }
205
+ setDraft(_extends({}, draft, {
206
+ custom: true,
207
+ text: serializeSpanDraft(draft)
208
+ }));
209
+ }, [
210
+ draft
211
+ ]);
212
+ return /*#__PURE__*/ _jsx(FormFieldGrid, _extends({
213
+ help: help
214
+ }, FormFieldGridProps, {
215
+ children: /*#__PURE__*/ _jsxs(Box, {
216
+ component: "fieldset",
217
+ sx: {
218
+ border: 0,
219
+ m: 0,
220
+ p: 0,
221
+ minWidth: 0
222
+ },
223
+ children: [
224
+ /*#__PURE__*/ _jsxs(Box, {
225
+ sx: {
226
+ display: 'flex',
227
+ alignItems: 'center',
228
+ justifyContent: 'space-between',
229
+ gap: 1
230
+ },
231
+ children: [
232
+ /*#__PURE__*/ _jsx(FormLabel, {
233
+ component: "legend",
234
+ error: !!invalid,
235
+ disabled: isDisabled,
236
+ required: isRequired,
237
+ sx: {
238
+ fontSize: '0.75rem'
239
+ },
240
+ children: label
241
+ }),
242
+ /*#__PURE__*/ _jsx(Button, {
243
+ size: "small",
244
+ variant: "text",
245
+ onClick: toggleCustom,
246
+ disabled: locked,
247
+ sx: {
248
+ minWidth: 0,
249
+ fontSize: '0.6875rem',
250
+ px: 0.5
251
+ },
252
+ children: draft.custom ? 'Use breakpoints' : 'Edit as text'
253
+ })
254
+ ]
255
+ }),
256
+ draft.custom ? /*#__PURE__*/ _jsx(MuiTextField, {
257
+ name: input.name,
258
+ value: draft.text,
259
+ onChange: handleTextChange,
260
+ onBlur: input.onBlur,
261
+ onFocus: input.onFocus,
262
+ size: "small",
263
+ fullWidth: true,
264
+ disabled: isDisabled,
265
+ placeholder: placeholder != null ? placeholder : 'xs:12 md:6',
266
+ slotProps: {
267
+ input: {
268
+ readOnly: isReadOnly
269
+ }
270
+ }
271
+ }) : /*#__PURE__*/ _jsx(Box, {
272
+ sx: {
273
+ display: 'grid',
274
+ gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
275
+ gap: 0.75,
276
+ mt: 0.5
277
+ },
278
+ children: cells.map(({ key, label: cellLabel })=>{
279
+ const current = key === 'base' ? draft.base : draft.values[key];
280
+ // MUI's prop is a scalar OR an object. Rather than dropping one
281
+ // of the two at serialize time, the unusable half is visibly
282
+ // out of play.
283
+ const disabled = locked || (key === 'base' ? anyBreakpointSet : baseSet);
284
+ return /*#__PURE__*/ _jsxs(Box, {
285
+ children: [
286
+ /*#__PURE__*/ _jsx(Typography, {
287
+ variant: "caption",
288
+ component: "label",
289
+ htmlFor: `${input.name}-${key}`,
290
+ sx: {
291
+ display: 'block',
292
+ color: 'text.secondary',
293
+ lineHeight: 1.4
294
+ },
295
+ children: cellLabel
296
+ }),
297
+ /*#__PURE__*/ _jsxs(Select, {
298
+ id: `${input.name}-${key}`,
299
+ size: "small",
300
+ fullWidth: true,
301
+ displayEmpty: true,
302
+ disabled: disabled,
303
+ value: current,
304
+ onChange: (event)=>{
305
+ var _event_target_value;
306
+ return handleCellChange(key, `${(_event_target_value = event.target.value) != null ? _event_target_value : ''}`);
307
+ },
308
+ onBlur: input.onBlur,
309
+ inputProps: {
310
+ 'aria-label': `${label} ${cellLabel}`
311
+ },
312
+ renderValue: (selected)=>isSet(selected) ? selected : '—',
313
+ sx: {
314
+ '& .MuiSelect-select': {
315
+ py: 0.5
316
+ }
317
+ },
318
+ children: [
319
+ /*#__PURE__*/ _jsx(MenuItem, {
320
+ value: "",
321
+ children: /*#__PURE__*/ _jsx("em", {
322
+ children: '—'
323
+ })
324
+ }),
325
+ optionsFor(current).map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
326
+ value: option,
327
+ children: option
328
+ }, option))
329
+ ]
330
+ })
331
+ ]
332
+ }, key);
333
+ })
334
+ }),
335
+ /*#__PURE__*/ _jsx(FormHelperText, {
336
+ error: !!invalid,
337
+ disabled: isDisabled,
338
+ children: invalid || (meta.touched || validateOnMount) && meta.warning || helperText || description
339
+ })
340
+ ]
341
+ })
342
+ }));
343
+ };
344
+ export default BreakpointSpanField;
345
+
346
+ //# sourceMappingURL=breakpoint-span.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx-forms/src/lib/mapper/breakpoint-span.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 {\n buildBreakpointSpan,\n parseBreakpointSpan,\n SPAN_BREAKPOINTS,\n type SpanBreakpoint,\n type SpanValue,\n} from '@aglyn/shared-data-enums'\nimport {\n Box,\n Button,\n FormHelperText,\n FormLabel,\n MenuItem,\n Select,\n TextField as MuiTextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { useFieldApi } from '../vendor/data-driven-forms'\nimport FormFieldGrid, { type FormFieldGridProps } from './form-field-grid'\nimport type { BaseFieldProps } from './types'\nimport { type ExtendedFieldMeta, validationError } from './validation-error'\n\n/**\n * BreakpointSpan (AGL-2486): the per-breakpoint editor for a MUI Grid cell's\n * **Span** and **Offset**.\n *\n * Both were free-text boxes taking a developer syntax — `xs:12 md:2` — with\n * the syntax explained only in a tooltip. Aglyn's authors are not reading the\n * MUI Grid docs, so the capability was there and unreachable: in practice a\n * cell got one number and never became responsive.\n *\n * The PERSISTED value is unchanged: still ONE string, still the same syntax,\n * parsed by the same shared pair the Grid element itself uses\n * (`parseBreakpointSpan`/`buildBreakpointSpan` in `@aglyn/shared-data-enums`).\n * This is an input affordance, not a shape change, so renderers, published\n * documents and existing nodes stay untouched — the same rule\n * {@link CssDimensionField} follows for CSS lengths.\n *\n * Two things the layout of this editor has to get right:\n *\n * - A value authored with NO breakpoint (`\"6\"`) is a scalar and applies at\n * every size. It is NOT the same string as `xs:6`, and MUI's prop is\n * either a scalar or an object — never both. So the row leads with an\n * **All** cell, and picking a breakpoint disables it (and vice versa)\n * rather than silently dropping one of the two.\n * - Anything this editor cannot model — a `{{token}}`, an unknown\n * breakpoint, a span wider than the offered list — must NOT be clobbered.\n * It falls back to a raw text box holding the string verbatim, and flips\n * back to the controls the moment the text becomes modellable again. The\n * same escape hatch is reachable on purpose (**Edit as text**) so the full\n * syntax stays available to anyone who wants it.\n */\n\n/** Draft state: what the row of controls shows, before serialization. */\nexport interface SpanDraft {\n /** The value is not modellable — the text box holds it verbatim. */\n custom: boolean\n /** Raw string, in custom mode only. */\n text: string\n /** The breakpoint-less value; `''` when unset. */\n base: string\n /** Per-breakpoint values as option strings; `''` when unset. */\n values: Record<SpanBreakpoint, string>\n}\n\nconst emptyValues = (): Record<SpanBreakpoint, string> =>\n SPAN_BREAKPOINTS.reduce(\n (acc, key) => {\n acc[key] = ''\n return acc\n },\n {} as Record<SpanBreakpoint, string>,\n )\n\n/** `''` is the only \"unset\"; `'0'` is a real offset an author can mean. */\nconst isSet = (value: string) => value !== '' && value !== undefined && value !== null\n\nexport const seedSpanDraft = (value: unknown): SpanDraft => {\n const parsed = parseBreakpointSpan(value as string | number)\n if (parsed.raw !== undefined) {\n return { custom: true, text: parsed.raw, base: '', values: emptyValues() }\n }\n const values = emptyValues()\n for (const key of SPAN_BREAKPOINTS) {\n const span = parsed.values?.[key]\n if (span !== undefined) values[key] = `${span}`\n }\n return {\n custom: false,\n text: '',\n base: parsed.base === undefined ? '' : `${parsed.base}`,\n values,\n }\n}\n\n/** `'auto'`/`'grow'` stay keywords; everything else is a number. */\nconst toSpanValue = (option: string): SpanValue =>\n option === 'auto' || option === 'grow' ? option : Number(option)\n\nexport const serializeSpanDraft = (draft: SpanDraft): string => {\n if (draft.custom) return draft.text\n if (isSet(draft.base)) return buildBreakpointSpan({ base: toSpanValue(draft.base) })\n const values: Partial<Record<SpanBreakpoint, SpanValue>> = {}\n for (const key of SPAN_BREAKPOINTS) {\n const option = draft.values[key]\n if (isSet(option)) values[key] = toSpanValue(option)\n }\n return Object.keys(values).length ? buildBreakpointSpan({ values }) : ''\n}\n\nexport interface BreakpointSpanProps extends BaseFieldProps {\n /** Offer MUI's `grow` keyword. False for Offset, which has no `grow`. */\n allowGrow?: boolean\n /** Lowest column count offered. 0 for Offset, 1 for Span. */\n minSpan?: number\n /** Highest column count offered; the container's `columns` default. */\n maxSpan?: number\n FormFieldGridProps?: FormFieldGridProps\n}\n\n/** Human labels for the cells, in the order they are rendered. */\nconst CELL_LABELS: Record<SpanBreakpoint | 'base', string> = {\n base: 'All',\n xs: 'xs',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'xl',\n}\n\nexport const BreakpointSpanField = (props: BreakpointSpanProps) => {\n const {\n input,\n isReadOnly,\n isDisabled,\n isRequired,\n label,\n placeholder,\n helperText,\n description,\n validateOnMount,\n meta,\n help,\n allowGrow = true,\n minSpan = 1,\n maxSpan = 12,\n FormFieldGridProps = {},\n // Leftovers from the attribute schema this field was authored with as a\n // TEXT_FIELD; they must never reach the DOM.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n inputProps: _inputProps,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n InputProps: _InputProps,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n multiline: _multiline,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n type: _type,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n component: _component,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n tokenOptions: _tokenOptions,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n tokenLabelContext: _tokenLabelContext,\n // Deliberately NOT spread onto the box below: the root here is a\n // `<fieldset>`, and a schema's leftover keys (`dataType`, `options`, …)\n // would land on the DOM as unknown attributes.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ...rest\n } = useFieldApi(props)\n const invalid = validationError(meta as ExtendedFieldMeta, validateOnMount)\n\n // A value persisted as a bare NUMBER (`size: 6`) is still a value the\n // author has to see; reading only strings would blank the row and then\n // overwrite the number on the first edit.\n const value =\n input.value === undefined || input.value === null ? '' : `${input.value}`\n\n const [draft, setDraft] = useState<SpanDraft>(() => seedSpanDraft(value))\n // Re-seed only when the value changed OUTSIDE this field (a different node\n // selected, an undo). Re-seeding from our own emits would fight the\n // author's half-finished text in custom mode.\n const emittedRef = useRef(value)\n useEffect(() => {\n if (value === emittedRef.current) return\n emittedRef.current = value\n setDraft(seedSpanDraft(value))\n }, [value])\n\n const commit = useCallback(\n (next: SpanDraft) => {\n const serialized = serializeSpanDraft(next)\n emittedRef.current = serialized\n // Text the author edited back into a modellable span gets the\n // structured controls back immediately, so the mode stays DERIVED from\n // the value rather than remembered in a flag that can go stale.\n const reparsed = parseBreakpointSpan(serialized)\n setDraft(\n next.custom && serialized.trim() !== '' && reparsed.raw === undefined\n ? seedSpanDraft(serialized)\n : next,\n )\n input.onChange(serialized)\n },\n [input],\n )\n\n const anyBreakpointSet = SPAN_BREAKPOINTS.some((key) => isSet(draft.values[key]))\n const baseSet = isSet(draft.base)\n const locked = isDisabled || isReadOnly\n\n /**\n * The options a cell offers. A stored value the list does not carry — a\n * span wider than `maxSpan` because the container overrode `columns` — is\n * appended rather than dropped, so selecting nothing else cannot silently\n * rewrite it.\n */\n const optionsFor = useCallback(\n (current: string) => {\n const options: string[] = ['auto']\n if (allowGrow) options.push('grow')\n for (let span = minSpan; span <= maxSpan; span += 1) {\n options.push(`${span}`)\n }\n if (isSet(current) && !options.includes(current)) options.push(current)\n return options\n },\n [allowGrow, maxSpan, minSpan],\n )\n\n const cells = useMemo(\n () => [\n { key: 'base' as const, label: CELL_LABELS.base },\n ...SPAN_BREAKPOINTS.map((key) => ({ key, label: CELL_LABELS[key] })),\n ],\n [],\n )\n\n const handleCellChange = useCallback(\n (key: SpanBreakpoint | 'base', option: string) => {\n if (key === 'base') {\n commit({ ...draft, base: option })\n return\n }\n commit({ ...draft, values: { ...draft.values, [key]: option } })\n },\n [commit, draft],\n )\n\n const handleTextChange = useCallback(\n (event: { target: { value: string } }) => {\n commit({ ...draft, custom: true, text: event.target.value })\n },\n [commit, draft],\n )\n\n const toggleCustom = useCallback(() => {\n if (draft.custom) {\n // Back to the controls, seeded from whatever the text now says. Text\n // the controls cannot model keeps the text box (seedSpanDraft returns\n // custom), which is the honest answer rather than a silent wipe.\n setDraft(seedSpanDraft(draft.text))\n return\n }\n setDraft({ ...draft, custom: true, text: serializeSpanDraft(draft) })\n }, [draft])\n\n return (\n <FormFieldGrid help={help} {...FormFieldGridProps}>\n {/* A plain box, NOT a FormControl: this field owns six inputs, and a\n FormControl parent both warns (\"multiple InputBase components\n inside a FormControl\") and pushes its own error/focus state into\n every one of them. Label and helper text are rendered directly and\n told their state instead. */}\n <Box component=\"fieldset\" sx={{ border: 0, m: 0, p: 0, minWidth: 0 }}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 1,\n }}\n >\n <FormLabel\n component=\"legend\"\n error={!!invalid}\n disabled={isDisabled}\n required={isRequired}\n sx={{ fontSize: '0.75rem' }}\n >\n {label}\n </FormLabel>\n <Button\n size=\"small\"\n variant=\"text\"\n onClick={toggleCustom}\n disabled={locked}\n sx={{ minWidth: 0, fontSize: '0.6875rem', px: 0.5 }}\n >\n {draft.custom ? 'Use breakpoints' : 'Edit as text'}\n </Button>\n </Box>\n\n {draft.custom ? (\n <MuiTextField\n name={input.name}\n value={draft.text}\n onChange={handleTextChange}\n onBlur={input.onBlur}\n onFocus={input.onFocus}\n size=\"small\"\n fullWidth\n disabled={isDisabled}\n placeholder={(placeholder as string) ?? 'xs:12 md:6'}\n slotProps={{ input: { readOnly: isReadOnly } }}\n />\n ) : (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',\n gap: 0.75,\n mt: 0.5,\n }}\n >\n {cells.map(({ key, label: cellLabel }) => {\n const current = key === 'base' ? draft.base : draft.values[key]\n // MUI's prop is a scalar OR an object. Rather than dropping one\n // of the two at serialize time, the unusable half is visibly\n // out of play.\n const disabled =\n locked ||\n (key === 'base' ? anyBreakpointSet : baseSet)\n return (\n <Box key={key}>\n <Typography\n variant=\"caption\"\n component=\"label\"\n htmlFor={`${input.name}-${key}`}\n sx={{\n display: 'block',\n color: 'text.secondary',\n lineHeight: 1.4,\n }}\n >\n {cellLabel}\n </Typography>\n <Select\n id={`${input.name}-${key}`}\n size=\"small\"\n fullWidth\n displayEmpty\n disabled={disabled}\n value={current}\n onChange={(event) =>\n handleCellChange(key, `${event.target.value ?? ''}`)\n }\n onBlur={input.onBlur}\n inputProps={{ 'aria-label': `${label} ${cellLabel}` }}\n renderValue={(selected) =>\n isSet(selected as string) ? (selected as string) : '—'\n }\n sx={{ '& .MuiSelect-select': { py: 0.5 } }}\n >\n <MenuItem value=\"\">\n <em>{'—'}</em>\n </MenuItem>\n {optionsFor(current).map((option) => (\n <MenuItem key={option} value={option}>\n {option}\n </MenuItem>\n ))}\n </Select>\n </Box>\n )\n })}\n </Box>\n )}\n\n <FormHelperText error={!!invalid} disabled={isDisabled}>\n {invalid ||\n ((meta.touched || validateOnMount) && meta.warning) ||\n helperText ||\n description}\n </FormHelperText>\n </Box>\n </FormFieldGrid>\n )\n}\n\nexport default BreakpointSpanField\n"],"names":["buildBreakpointSpan","parseBreakpointSpan","SPAN_BREAKPOINTS","Box","Button","FormHelperText","FormLabel","MenuItem","Select","TextField","MuiTextField","Typography","useCallback","useEffect","useMemo","useRef","useState","useFieldApi","FormFieldGrid","validationError","emptyValues","reduce","acc","key","isSet","value","undefined","seedSpanDraft","parsed","raw","custom","text","base","values","span","toSpanValue","option","Number","serializeSpanDraft","draft","Object","keys","length","CELL_LABELS","xs","sm","md","lg","xl","BreakpointSpanField","props","input","isReadOnly","isDisabled","isRequired","label","placeholder","helperText","description","validateOnMount","meta","help","allowGrow","minSpan","maxSpan","FormFieldGridProps","inputProps","_inputProps","InputProps","_InputProps","multiline","_multiline","type","_type","component","_component","tokenOptions","_tokenOptions","tokenLabelContext","_tokenLabelContext","rest","invalid","setDraft","emittedRef","current","commit","next","serialized","reparsed","trim","onChange","anyBreakpointSet","some","baseSet","locked","optionsFor","options","push","includes","cells","map","handleCellChange","handleTextChange","event","target","toggleCustom","sx","border","m","p","minWidth","display","alignItems","justifyContent","gap","error","disabled","required","fontSize","size","variant","onClick","px","name","onBlur","onFocus","fullWidth","slotProps","readOnly","gridTemplateColumns","mt","cellLabel","htmlFor","color","lineHeight","id","displayEmpty","renderValue","selected","py","em","touched","warning"],"mappings":"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"}
@@ -0,0 +1,43 @@
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
+ /**
18
+ * Ported from `@data-driven-forms/mui-component-mapper` (Apache-2.0) and
19
+ * updated for the current MUI API (`slotProps` instead of `inputProps`).
20
+ */
21
+ import { type CheckboxProps as MuiCheckboxProps, type FormControlLabelProps, type FormControlProps, type FormGroupProps, type FormHelperTextProps, type FormLabelProps } from '@mui/material';
22
+ import { type FormFieldGridProps } from './form-field-grid';
23
+ import type { BaseFieldProps, OptionValue, SelectOption } from './types';
24
+ export interface SingleCheckboxProps extends BaseFieldProps {
25
+ /** Offer the reset-to-unset affordance, as the switch does. */
26
+ clearable?: boolean;
27
+ /** The state shown while nothing is stored, as the switch takes it. */
28
+ unsetChecked?: boolean;
29
+ FormFieldGridProps?: FormFieldGridProps;
30
+ FormControlProps?: FormControlProps;
31
+ FormGroupProps?: FormGroupProps;
32
+ FormControlLabelProps?: Partial<FormControlLabelProps>;
33
+ CheckboxProps?: MuiCheckboxProps;
34
+ FormLabelProps?: FormLabelProps;
35
+ FormHelperTextProps?: FormHelperTextProps;
36
+ inputProps?: Record<string, any>;
37
+ }
38
+ export interface CheckboxProps<T = OptionValue> extends SingleCheckboxProps {
39
+ options?: SelectOption<T>[];
40
+ }
41
+ export declare const SingleCheckbox: (props: SingleCheckboxProps) => import("react").JSX.Element;
42
+ export declare function Checkbox<T = OptionValue>({ options, ...props }: CheckboxProps<T>): import("react").JSX.Element;
43
+ export default Checkbox;
@@ -0,0 +1,111 @@
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, jsxs as _jsxs } 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
+ */ /**
20
+ * Ported from `@data-driven-forms/mui-component-mapper` (Apache-2.0) and
21
+ * updated for the current MUI API (`slotProps` instead of `inputProps`).
22
+ */ import { Checkbox as MuiCheckbox, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel } from "@mui/material";
23
+ import { useFieldApi } from "../vendor/data-driven-forms.js";
24
+ import { useStoredFieldHasValue } from "./stored-field-value.js";
25
+ import FormFieldGrid, { buildFieldClear } from "./form-field-grid.js";
26
+ import MultipleChoiceList from "./multiple-choice-list.js";
27
+ import { validationError } from "./validation-error.js";
28
+ export const SingleCheckbox = (props)=>{
29
+ const _useFieldApi = useFieldApi(_extends({}, props, {
30
+ type: 'checkbox'
31
+ })), { input, isReadOnly, isDisabled, isRequired, label, helperText, description, validateOnMount, meta, help, clearable, unsetChecked, FormFieldGridProps = {}, FormControlProps = {}, FormGroupProps = {}, FormControlLabelProps = {}, CheckboxProps = {}, FormLabelProps = {}, FormHelperTextProps = {}, inputProps } = _useFieldApi, rest = _object_without_properties_loose(_useFieldApi, [
32
+ "input",
33
+ "isReadOnly",
34
+ "isDisabled",
35
+ "isRequired",
36
+ "label",
37
+ "helperText",
38
+ "description",
39
+ "validateOnMount",
40
+ "meta",
41
+ "help",
42
+ "clearable",
43
+ "unsetChecked",
44
+ "FormFieldGridProps",
45
+ "FormControlProps",
46
+ "FormGroupProps",
47
+ "FormControlLabelProps",
48
+ "CheckboxProps",
49
+ "FormLabelProps",
50
+ "FormHelperTextProps",
51
+ "inputProps"
52
+ ]);
53
+ const invalid = validationError(meta, validateOnMount);
54
+ const text = invalid || (meta.touched || validateOnMount) && meta.warning || helperText || description;
55
+ const hasValue = useStoredFieldHasValue(input.name);
56
+ const clear = buildFieldClear({
57
+ clearable,
58
+ label,
59
+ hasValue,
60
+ locked: Boolean(isDisabled || isReadOnly),
61
+ onClear: ()=>input.onChange(undefined)
62
+ });
63
+ return /*#__PURE__*/ _jsx(FormFieldGrid, _extends({
64
+ help: help,
65
+ clear: clear
66
+ }, FormFieldGridProps, {
67
+ children: /*#__PURE__*/ _jsx(FormControl, _extends({
68
+ required: isRequired,
69
+ error: !!invalid,
70
+ component: "fieldset"
71
+ }, FormControlProps, {
72
+ children: /*#__PURE__*/ _jsxs(FormGroup, _extends({}, FormGroupProps, {
73
+ children: [
74
+ /*#__PURE__*/ _jsx(FormControlLabel, _extends({}, FormControlLabelProps, {
75
+ control: /*#__PURE__*/ _jsx(MuiCheckbox, _extends({}, input, {
76
+ checked: hasValue ? input.checked : Boolean(unsetChecked)
77
+ }, CheckboxProps, {
78
+ disabled: isDisabled || isReadOnly,
79
+ value: input.name,
80
+ slotProps: {
81
+ input: _extends({
82
+ readOnly: isReadOnly
83
+ }, inputProps)
84
+ }
85
+ }, rest)),
86
+ disabled: isDisabled || isReadOnly,
87
+ label: /*#__PURE__*/ _jsx(FormLabel, _extends({}, FormLabelProps, {
88
+ children: label
89
+ }))
90
+ })),
91
+ text && /*#__PURE__*/ _jsx(FormHelperText, _extends({}, FormHelperTextProps, {
92
+ children: text
93
+ }))
94
+ ]
95
+ }))
96
+ }))
97
+ }));
98
+ };
99
+ export function Checkbox(_0) {
100
+ let { options } = _0, props = _object_without_properties_loose(_0, [
101
+ "options"
102
+ ]);
103
+ return options ? // The list renders option values opaquely, so the wider generic is
104
+ // safe to narrow to the common OptionValue shape.
105
+ /*#__PURE__*/ _jsx(MultipleChoiceList, _extends({
106
+ options: options
107
+ }, props)) : /*#__PURE__*/ _jsx(SingleCheckbox, _extends({}, props));
108
+ }
109
+ export default Checkbox;
110
+
111
+ //# sourceMappingURL=checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx-forms/src/lib/mapper/checkbox.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\n/**\n * Ported from `@data-driven-forms/mui-component-mapper` (Apache-2.0) and\n * updated for the current MUI API (`slotProps` instead of `inputProps`).\n */\n\nimport {\n Checkbox as MuiCheckbox,\n type CheckboxProps as MuiCheckboxProps,\n FormControl,\n type FormControlLabelProps,\n FormControlLabel,\n type FormControlProps,\n FormGroup,\n type FormGroupProps,\n FormHelperText,\n type FormHelperTextProps,\n FormLabel,\n type FormLabelProps,\n} from '@mui/material'\n\nimport { useFieldApi } from '../vendor/data-driven-forms'\nimport { useStoredFieldHasValue } from './stored-field-value'\nimport FormFieldGrid, {\n buildFieldClear,\n type FormFieldGridProps,\n} from './form-field-grid'\nimport MultipleChoiceList from './multiple-choice-list'\nimport type { BaseFieldProps, OptionValue, SelectOption } from './types'\nimport { type ExtendedFieldMeta, validationError } from './validation-error'\n\nexport interface SingleCheckboxProps extends BaseFieldProps {\n /** Offer the reset-to-unset affordance, as the switch does. */\n clearable?: boolean\n /** The state shown while nothing is stored, as the switch takes it. */\n unsetChecked?: boolean\n FormFieldGridProps?: FormFieldGridProps\n FormControlProps?: FormControlProps\n FormGroupProps?: FormGroupProps\n FormControlLabelProps?: Partial<FormControlLabelProps>\n CheckboxProps?: MuiCheckboxProps\n FormLabelProps?: FormLabelProps\n FormHelperTextProps?: FormHelperTextProps\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputProps?: Record<string, any>\n}\n\nexport interface CheckboxProps<T = OptionValue> extends SingleCheckboxProps {\n options?: SelectOption<T>[]\n}\n\nexport const SingleCheckbox = (props: SingleCheckboxProps) => {\n const {\n input,\n isReadOnly,\n isDisabled,\n isRequired,\n label,\n helperText,\n description,\n validateOnMount,\n meta,\n help,\n clearable,\n unsetChecked,\n FormFieldGridProps = {},\n FormControlProps = {},\n FormGroupProps = {},\n FormControlLabelProps = {},\n CheckboxProps = {},\n FormLabelProps = {},\n FormHelperTextProps = {},\n inputProps,\n ...rest\n } = useFieldApi({\n ...props,\n type: 'checkbox',\n })\n const invalid = validationError(meta as ExtendedFieldMeta, validateOnMount)\n const text =\n invalid ||\n ((meta.touched || validateOnMount) && meta.warning) ||\n helperText ||\n description\n const hasValue = useStoredFieldHasValue(input.name)\n const clear = buildFieldClear({\n clearable,\n label,\n hasValue,\n locked: Boolean(isDisabled || isReadOnly),\n onClear: () => input.onChange(undefined),\n })\n\n return (\n <FormFieldGrid help={help} clear={clear} {...FormFieldGridProps}>\n <FormControl\n required={isRequired}\n error={!!invalid}\n component=\"fieldset\"\n {...FormControlProps}\n >\n <FormGroup {...FormGroupProps}>\n <FormControlLabel\n {...FormControlLabelProps}\n control={\n <MuiCheckbox\n {...input}\n checked={hasValue ? input.checked : Boolean(unsetChecked)}\n {...CheckboxProps}\n disabled={isDisabled || isReadOnly}\n value={input.name}\n slotProps={{\n input: { readOnly: isReadOnly, ...inputProps },\n }}\n {...rest}\n />\n }\n disabled={isDisabled || isReadOnly}\n label={<FormLabel {...FormLabelProps}>{label}</FormLabel>}\n />\n {text && (\n <FormHelperText {...FormHelperTextProps}>{text}</FormHelperText>\n )}\n </FormGroup>\n </FormControl>\n </FormFieldGrid>\n )\n}\n\nexport function Checkbox<T = OptionValue>({\n options,\n ...props\n}: CheckboxProps<T>) {\n return options ? (\n // The list renders option values opaquely, so the wider generic is\n // safe to narrow to the common OptionValue shape.\n <MultipleChoiceList options={options as SelectOption<OptionValue>[]} {...props} />\n ) : (\n <SingleCheckbox {...props} />\n )\n}\n\nexport default Checkbox\n"],"names":["Checkbox","MuiCheckbox","FormControl","FormControlLabel","FormGroup","FormHelperText","FormLabel","useFieldApi","useStoredFieldHasValue","FormFieldGrid","buildFieldClear","MultipleChoiceList","validationError","SingleCheckbox","props","type","input","isReadOnly","isDisabled","isRequired","label","helperText","description","validateOnMount","meta","help","clearable","unsetChecked","FormFieldGridProps","FormControlProps","FormGroupProps","FormControlLabelProps","CheckboxProps","FormLabelProps","FormHelperTextProps","inputProps","rest","invalid","text","touched","warning","hasValue","name","clear","locked","Boolean","onClear","onChange","undefined","required","error","component","control","checked","disabled","value","slotProps","readOnly","options"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;CAGC,GAED,SACEA,YAAYC,WAAW,EAEvBC,WAAW,EAEXC,gBAAgB,EAEhBC,SAAS,EAETC,cAAc,EAEdC,SAAS,QAEJ,gBAAe;AAEtB,SAASC,WAAW,QAAQ,iCAA6B;AACzD,SAASC,sBAAsB,QAAQ,0BAAsB;AAC7D,OAAOC,iBACLC,eAAe,QAEV,uBAAmB;AAC1B,OAAOC,wBAAwB,4BAAwB;AAEvD,SAAiCC,eAAe,QAAQ,wBAAoB;AAsB5E,OAAO,MAAMC,iBAAiB,CAACC;IAC7B,MAsBIP,eAAAA,YAAY,aACXO;QACHC,MAAM;SAxBF,EACJC,KAAK,EACLC,UAAU,EACVC,UAAU,EACVC,UAAU,EACVC,KAAK,EACLC,UAAU,EACVC,WAAW,EACXC,eAAe,EACfC,IAAI,EACJC,IAAI,EACJC,SAAS,EACTC,YAAY,EACZC,qBAAqB,CAAC,CAAC,EACvBC,mBAAmB,CAAC,CAAC,EACrBC,iBAAiB,CAAC,CAAC,EACnBC,wBAAwB,CAAC,CAAC,EAC1BC,gBAAgB,CAAC,CAAC,EAClBC,iBAAiB,CAAC,CAAC,EACnBC,sBAAsB,CAAC,CAAC,EACxBC,UAAU,EAEX,GAAG5B,cADC6B,wCACD7B;;;;;;;;;;;;;;;;;;;;;;IAIJ,MAAM8B,UAAUzB,gBAAgBY,MAA2BD;IAC3D,MAAMe,OACJD,WACC,AAACb,CAAAA,KAAKe,OAAO,IAAIhB,eAAc,KAAMC,KAAKgB,OAAO,IAClDnB,cACAC;IACF,MAAMmB,WAAWjC,uBAAuBQ,MAAM0B,IAAI;IAClD,MAAMC,QAAQjC,gBAAgB;QAC5BgB;QACAN;QACAqB;QACAG,QAAQC,QAAQ3B,cAAcD;QAC9B6B,SAAS,IAAM9B,MAAM+B,QAAQ,CAACC;IAChC;IAEA,qBACE,KAACvC;QAAcgB,MAAMA;QAAMkB,OAAOA;OAAWf;kBAC3C,cAAA,KAAC1B;YACC+C,UAAU9B;YACV+B,OAAO,CAAC,CAACb;YACTc,WAAU;WACNtB;sBAEJ,cAAA,MAACzB,wBAAc0B;;kCACb,KAAC3B,+BACK4B;wBACJqB,uBACE,KAACnD,0BACKe;4BACJqC,SAASZ,WAAWzB,MAAMqC,OAAO,GAAGR,QAAQlB;2BACxCK;4BACJsB,UAAUpC,cAAcD;4BACxBsC,OAAOvC,MAAM0B,IAAI;4BACjBc,WAAW;gCACTxC,OAAO;oCAAEyC,UAAUxC;mCAAekB;4BACpC;2BACIC;wBAGRkB,UAAUpC,cAAcD;wBACxBG,qBAAO,KAACd,wBAAc2B;sCAAiBb;;;oBAExCkB,sBACC,KAACjC,6BAAmB6B;kCAAsBI;;;;;;AAMtD,EAAC;AAED,OAAO,SAAStC,SAA0B,EAGvB;QAHuB,EACxC0D,OAAO,EAEU,OADd5C;;;IAEH,OAAO4C,UACL,mEAAmE;IACnE,kDAAkD;kBAClD,KAAC/C;QAAmB+C,SAASA;OAA4C5C,wBAEzE,KAACD,6BAAmBC;AAExB;AAEA,eAAed,SAAQ"}