attaform 0.28.0 → 0.29.0

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 (64) hide show
  1. package/dist/abstract.d.mts +5 -5
  2. package/dist/abstract.mjs +4 -4
  3. package/dist/chunks/fingerprint.mjs +1 -1
  4. package/dist/chunks/fingerprint2.mjs +2 -2
  5. package/dist/dev/abstract.mjs +4 -4
  6. package/dist/dev/chunks/devtools.mjs +1 -1
  7. package/dist/dev/chunks/fingerprint.mjs +1 -1
  8. package/dist/dev/chunks/fingerprint2.mjs +2 -2
  9. package/dist/dev/directive.mjs +1 -1
  10. package/dist/dev/history.mjs +1 -1
  11. package/dist/dev/index.mjs +5 -5
  12. package/dist/dev/runtime/plugins/attaform.mjs +1 -1
  13. package/dist/dev/shared/{attaform-dev.Dr2YzS5B.mjs → attaform-dev.A-TpJW0B.mjs} +11 -1
  14. package/dist/dev/shared/{attaform-dev.oYrkP9dj.mjs → attaform-dev.BO-71R54.mjs} +51 -158
  15. package/dist/dev/shared/{attaform-dev.6qxD-Yqo.mjs → attaform-dev.BgM6FdtA.mjs} +143 -36
  16. package/dist/{shared/attaform.h0i6LijT.mjs → dev/shared/attaform-dev.ButTkwHd.mjs} +149 -16
  17. package/dist/{shared/attaform.BJGA_UOS.mjs → dev/shared/attaform-dev.BxfsuwBR.mjs} +8 -0
  18. package/dist/dev/shared/{attaform-dev.P7cseiEG.mjs → attaform-dev.D8aoKb89.mjs} +13 -4
  19. package/dist/dev/shared/{attaform-dev.BXE2cr0L.mjs → attaform-dev.DD5m2W51.mjs} +1 -1
  20. package/dist/dev/shared/{attaform-dev.WmuhD_CZ.mjs → attaform-dev.DHuydLAC.mjs} +344 -96
  21. package/dist/dev/shared/{attaform-dev.BR8u0YOZ.mjs → attaform-dev.DrzObAZo.mjs} +4 -4
  22. package/dist/dev/shared/{attaform-dev.D2I8e_Mm.mjs → attaform-dev.q6UutkCx.mjs} +170 -132
  23. package/dist/dev/zod-v3.mjs +6 -6
  24. package/dist/dev/zod-v4.mjs +6 -6
  25. package/dist/dev/zod.mjs +5 -5
  26. package/dist/directive.d.mts +2 -2
  27. package/dist/directive.mjs +1 -1
  28. package/dist/history.d.mts +1 -1
  29. package/dist/history.mjs +1 -1
  30. package/dist/index.d.mts +9 -7
  31. package/dist/index.mjs +5 -5
  32. package/dist/nuxt.d.mts +10 -10
  33. package/dist/runtime/plugins/attaform.mjs +1 -1
  34. package/dist/shared/{attaform.C09fpdLS.mjs → attaform.B0dKL8ST.mjs} +143 -36
  35. package/dist/shared/{attaform.Cs2Rbdlo.mjs → attaform.BK0cgu2K.mjs} +123 -139
  36. package/dist/shared/{attaform.D6DCnnQu.mjs → attaform.BndjUUYX.mjs} +4 -4
  37. package/dist/{dev/shared/attaform-dev.BJGA_UOS.mjs → shared/attaform.BxfsuwBR.mjs} +8 -0
  38. package/dist/shared/{attaform.NLmerepI.mjs → attaform.C2MVyuxC.mjs} +42 -151
  39. package/dist/shared/{attaform.B4VkS43-.d.mts → attaform.CIWLMY-R.d.mts} +1 -1
  40. package/dist/shared/{attaform.B8k8JrmK.mjs → attaform.CZMAYwSK.mjs} +338 -95
  41. package/dist/shared/{attaform.wfY8XFvm.mjs → attaform.CZYt_5N_.mjs} +11 -1
  42. package/dist/shared/{attaform.Cgu-hdSb.d.mts → attaform.CsoeRi3P.d.mts} +224 -32
  43. package/dist/{dev/shared/attaform-dev.By4PRjt0.mjs → shared/attaform.Cvao8bW5.mjs} +132 -22
  44. package/dist/shared/{attaform.Dq4vWxuG.mjs → attaform.D0x-qSXm.mjs} +1 -1
  45. package/dist/shared/{attaform.CJP3RkGa.mjs → attaform.D1fnTifF.mjs} +168 -132
  46. package/dist/shared/{attaform.D5V4tZWq.d.mts → attaform.DDtqHYv1.d.mts} +88 -7
  47. package/dist/shared/{attaform.uLbun31C.mjs → attaform.DffRL5pP.mjs} +12 -4
  48. package/dist/shared/{attaform.JfSWdEcb.d.mts → attaform.axHXVQO7.d.mts} +1 -1
  49. package/dist/transforms.d.mts +0 -22
  50. package/dist/transforms.mjs +1 -1
  51. package/dist/vite.d.mts +13 -4
  52. package/dist/vite.mjs +3 -2
  53. package/dist/zod-v3.d.mts +6 -4
  54. package/dist/zod-v3.mjs +6 -6
  55. package/dist/zod-v4.d.mts +14 -27
  56. package/dist/zod-v4.mjs +6 -6
  57. package/dist/zod.d.mts +4 -4
  58. package/dist/zod.mjs +5 -5
  59. package/package.json +17 -14
  60. package/skills/attaform/SKILL.md +5 -2
  61. package/skills/attaform/references/custom-components.md +7 -2
  62. package/skills/attaform/references/errors.md +8 -3
  63. package/skills/attaform/references/saving.md +77 -0
  64. package/skills/attaform/references/wizards.md +10 -8
@@ -1,4 +1,4 @@
1
- import { NodeTypes, createCompoundExpression, createSimpleExpression, ElementTypes, processExpression } from '@vue/compiler-core';
1
+ import { NodeTypes, ElementTypes, createCompoundExpression, createSimpleExpression, processExpression } from '@vue/compiler-core';
2
2
  import { S as SSR_COMPONENT_HOST_MODIFIER, V as V_REGISTER_COMPILED_MODIFIER } from './attaform.KvlEedlF.mjs';
3
3
 
4
4
  function getSummarizedProps(node) {
@@ -40,6 +40,10 @@ function removePropsByName(props, propNames) {
40
40
  props.splice(index, 1);
41
41
  }
42
42
  }
43
+ function toExpressionArray(value) {
44
+ if (value === void 0) return void 0;
45
+ return Array.isArray(value) ? value : [value];
46
+ }
43
47
  function isExactKey(summarizedKey, name) {
44
48
  return summarizedKey === name || summarizedKey === `"${name}"`;
45
49
  }
@@ -64,54 +68,13 @@ function flattenExpression(exp) {
64
68
  return out;
65
69
  }
66
70
 
67
- function generateEqualityExpression$1(selectValue, optionValue, previousOptionExpressions) {
68
- const multipleExpression = previousOptionExpressions?.[0];
69
- if (multipleExpression === void 0) {
70
- throw new Error(
71
- "Programming error: `multiple` expression for `select` node not generated while transforming AST"
72
- );
73
- }
74
- const optExpressions = previousOptionExpressions.slice(1);
75
- const noMultipleOptExpressions = optExpressions.reduce(
76
- (acc, curr, index) => {
77
- if (index === 0) {
78
- acc.push("(");
79
- }
80
- acc.push(...curr);
81
- if (index < optExpressions.length - 1) {
82
- acc.push(" || ");
83
- }
84
- if (index === optExpressions.length - 1) {
85
- acc.push(")");
86
- }
87
- return acc;
88
- },
89
- []
90
- );
71
+ function generateEqualityExpression$1(selectValue, optionValue, multipleExpression) {
91
72
  const selectValueArr = Array.isArray(selectValue) ? selectValue : [selectValue];
92
73
  const optionValueArr = Array.isArray(optionValue) ? optionValue : [optionValue];
93
74
  function getImplicitTrueMultipleExpression(expression) {
94
75
  if (expression.length === 1 && expression[0] === "") return [`true`];
95
76
  return expression;
96
77
  }
97
- previousOptionExpressions.push(["(", ...selectValueArr, ") === (", ...optionValueArr, ")"]);
98
- if (!noMultipleOptExpressions.length) {
99
- return [
100
- "(",
101
- ...getImplicitTrueMultipleExpression(multipleExpression),
102
- `) ? ((`,
103
- ...selectValueArr,
104
- `)?.innerRef?.value?.findIndex?.(el => el === (`,
105
- ...optionValueArr,
106
- `)) > -1) : (typeof (`,
107
- ...selectValueArr,
108
- `)?.innerRef?.value !== 'object' && String((`,
109
- ...selectValueArr,
110
- `)?.innerRef?.value) === String((`,
111
- ...optionValueArr,
112
- `)))`
113
- ];
114
- }
115
78
  return [
116
79
  "(",
117
80
  ...getImplicitTrueMultipleExpression(multipleExpression),
@@ -119,16 +82,13 @@ function generateEqualityExpression$1(selectValue, optionValue, previousOptionEx
119
82
  ...selectValueArr,
120
83
  `)?.innerRef?.value?.findIndex?.(el => el === (`,
121
84
  ...optionValueArr,
122
- `)) > -1) : ((`,
123
- ...noMultipleOptExpressions,
124
- // if true, we already found the relevant option
125
- `) ? false : (typeof (`,
85
+ `)) > -1) : (typeof (`,
126
86
  ...selectValueArr,
127
- `)?.innerRef?.value !== 'object' && String((`,
87
+ `)?.innerRef?.value !== 'object' && (`,
128
88
  ...selectValueArr,
129
- `)?.innerRef?.value) === String((`,
89
+ `)?.displayValue?.value === String((`,
130
90
  ...optionValueArr,
131
- `))))`
91
+ `)))`
132
92
  ];
133
93
  }
134
94
  function extractMultipleFromSelectSummarizedProps(props) {
@@ -143,7 +103,7 @@ function extractMultipleFromSelectSummarizedProps(props) {
143
103
  const value = props[priorityIndex]?.value;
144
104
  return typeof value === "string" ? value.replace(/'|"/g, "") : value ?? "true";
145
105
  }
146
- const RECURSABLE_NODE_TYPES$1 = /* @__PURE__ */ new Set([
106
+ const RECURSABLE_NODE_TYPES = /* @__PURE__ */ new Set([
147
107
  NodeTypes.ELEMENT,
148
108
  NodeTypes.FOR,
149
109
  NodeTypes.IF,
@@ -170,6 +130,57 @@ function inferOptionValueFromChildren(node) {
170
130
  const text = only.content.trim();
171
131
  return JSON.stringify(text);
172
132
  }
133
+ const pendingOptionBindings = /* @__PURE__ */ new WeakMap();
134
+ function applyPendingOptionBinding(node, pending) {
135
+ const optionProps = getSummarizedProps(node);
136
+ const valueIndex = optionProps.findIndex((p) => isExactKey(p.key, "value"));
137
+ let optionValueSummarizedProp;
138
+ if (valueIndex >= 0 && valueIndex < optionProps.length) {
139
+ optionValueSummarizedProp = optionProps[valueIndex];
140
+ } else {
141
+ const fallback = inferOptionValueFromChildren(node);
142
+ if (fallback === null) {
143
+ return;
144
+ }
145
+ optionValueSummarizedProp = { key: "value", value: fallback };
146
+ }
147
+ const props = node.props;
148
+ const snapshot = [...props];
149
+ try {
150
+ removePropsByName(props, ["selected"]);
151
+ const authorSelectedArr = toExpressionArray(
152
+ optionProps.find((p) => isExactKey(p.key, "selected"))?.value
153
+ );
154
+ const registerArr = toExpressionArray(pending.registerValue) ?? ["undefined"];
155
+ const boundExpression = generateEqualityExpression$1(
156
+ pending.registerValue,
157
+ optionValueSummarizedProp?.value ?? "undefined",
158
+ pending.multiple
159
+ );
160
+ props.push({
161
+ arg: createSimpleExpression("selected", true),
162
+ exp: createCompoundExpression(
163
+ authorSelectedArr === void 0 ? boundExpression : [
164
+ "((",
165
+ ...registerArr,
166
+ ") == null ? (",
167
+ ...authorSelectedArr,
168
+ ") : (",
169
+ ...boundExpression,
170
+ "))"
171
+ ]
172
+ ),
173
+ name: "bind",
174
+ modifiers: [],
175
+ type: NodeTypes.DIRECTIVE,
176
+ loc: node.loc
177
+ });
178
+ } catch (err) {
179
+ props.length = 0;
180
+ props.push(...snapshot);
181
+ console.error("[attaform] component-bridge transform: option binding failed, skipping:", err);
182
+ }
183
+ }
173
184
  const componentBridgeTransform = (node, context) => {
174
185
  const snapshots = [];
175
186
  const snapshotProps = (target) => {
@@ -177,51 +188,33 @@ const componentBridgeTransform = (node, context) => {
177
188
  snapshots.push({ target, snapshot: [...target] });
178
189
  };
179
190
  try {
180
- let traverseSelectNode = function(_node, previousOptionExpressions2) {
191
+ let traverseSelectNode = function(_node, multipleExpression2) {
181
192
  const isOption = _node.type === NodeTypes.ELEMENT && _node.tag === "option";
182
193
  if (!isOption) {
183
- if (!RECURSABLE_NODE_TYPES$1.has(_node.type)) return;
194
+ if (!RECURSABLE_NODE_TYPES.has(_node.type)) return;
184
195
  const hasChildren = "children" in _node;
185
196
  if (!hasChildren) return;
186
197
  for (const child of _node.children) {
187
198
  if (typeof child === "symbol" || typeof child === "string") continue;
188
199
  if (child.type === NodeTypes.SIMPLE_EXPRESSION) continue;
189
- traverseSelectNode(child, previousOptionExpressions2);
200
+ traverseSelectNode(child, multipleExpression2);
190
201
  }
191
202
  return;
192
203
  }
193
204
  hasSlottedOptions = true;
194
- const optionProps = getSummarizedProps(_node);
195
- const valueIndex = optionProps.findIndex((p) => isExactKey(p.key, "value"));
196
- let optionValueSummarizedProp;
197
- if (valueIndex >= 0 && valueIndex < optionProps.length) {
198
- optionValueSummarizedProp = optionProps[valueIndex];
199
- } else {
200
- const fallback = inferOptionValueFromChildren(_node);
201
- if (fallback === null) {
202
- return;
203
- }
204
- optionValueSummarizedProp = { key: "value", value: fallback };
205
- }
206
- const props = _node.props;
207
- snapshotProps(props);
208
- removePropsByName(props, ["selected"]);
209
- const newProp = {
210
- arg: createSimpleExpression("selected", true),
211
- exp: createCompoundExpression(
212
- generateEqualityExpression$1(
213
- registerSummarizedProp?.value ?? "undefined",
214
- optionValueSummarizedProp?.value ?? "undefined",
215
- previousOptionExpressions2
216
- )
217
- ),
218
- name: "bind",
219
- modifiers: [],
220
- type: NodeTypes.DIRECTIVE,
221
- loc: _node.loc
222
- };
223
- props.push(newProp);
205
+ pendingOptionBindings.set(_node, {
206
+ registerValue: registerSummarizedProp?.value ?? "undefined",
207
+ multiple: multipleExpression2
208
+ });
224
209
  };
210
+ if (node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.ELEMENT) {
211
+ const pending = pendingOptionBindings.get(node);
212
+ if (pending !== void 0) {
213
+ pendingOptionBindings.delete(node);
214
+ applyPendingOptionBinding(node, pending);
215
+ return;
216
+ }
217
+ }
225
218
  const isSelect = node.type === NodeTypes.ELEMENT && node.tag === "select";
226
219
  const isCustomComponent = node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.COMPONENT;
227
220
  const isKebabCustomElement = node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.ELEMENT && node.tag.includes("-") && !NATIVE_FORM_TAGS.has(node.tag);
@@ -233,25 +226,32 @@ const componentBridgeTransform = (node, context) => {
233
226
  const registerSummarizedProp = selectSummarizedProps[registerIndex];
234
227
  const selectLoc = node.loc;
235
228
  let hasSlottedOptions = false;
236
- const multipleExpression = extractMultipleFromSelectSummarizedProps(selectSummarizedProps);
237
- const previousOptionExpressions = typeof multipleExpression === "string" ? [[multipleExpression]] : [multipleExpression];
229
+ const rawMultipleExpression = extractMultipleFromSelectSummarizedProps(selectSummarizedProps);
230
+ const multipleExpression = typeof rawMultipleExpression === "string" ? [rawMultipleExpression] : rawMultipleExpression;
238
231
  for (const child of node.children) {
239
- traverseSelectNode(child, previousOptionExpressions);
232
+ traverseSelectNode(child, multipleExpression);
240
233
  }
241
- const isStaticallyNonMultiple = multipleExpression === "false";
234
+ const isStaticallyNonMultiple = rawMultipleExpression === "false";
242
235
  const isComponentHost = isCustomComponent || isKebabCustomElement;
243
236
  const isSelectLikeHost = isSelect || isComponentHost && hasSlottedOptions;
244
237
  const isPlainComponentHost = isComponentHost && !hasSlottedOptions;
245
238
  const selectProps = node.props;
239
+ const authorSelectValueArr = toExpressionArray(
240
+ selectSummarizedProps.find((p) => isExactKey(p.key, "value"))?.value
241
+ );
246
242
  snapshotProps(selectProps);
247
243
  removePropsByName(selectProps, ["value"]);
248
244
  if (isStaticallyNonMultiple && isSelectLikeHost) {
249
245
  const valuePropExpArray = Array.isArray(registerSummarizedProp?.value) ? registerSummarizedProp.value : [registerSummarizedProp?.value ?? "undefined"];
250
- const initExpression = createCompoundExpression([
251
- "(",
252
- ...valuePropExpArray,
253
- ")?.displayValue.value"
254
- ]);
246
+ const initExpression = createCompoundExpression(
247
+ authorSelectValueArr === void 0 ? ["(", ...valuePropExpArray, ")?.displayValue.value"] : [
248
+ "((",
249
+ ...valuePropExpArray,
250
+ ")?.displayValue.value ?? (",
251
+ ...authorSelectValueArr,
252
+ "))"
253
+ ]
254
+ );
255
255
  const simpleExpression = createSimpleExpression(flattenExpression(initExpression), false);
256
256
  let outputExp;
257
257
  try {
@@ -470,26 +470,41 @@ const inputTextAreaNodeTransform = (node) => {
470
470
  const isStaticRadio = typeProp !== void 0 && isStaticTypeOneOf(typeProp.value, ["radio"]);
471
471
  const isDynamicType = typeProp !== void 0 && isDynamicTypeValue(typeProp.value);
472
472
  const keepStaticValue = isStaticCheckbox || isStaticRadio || isDynamicType;
473
+ const authorCheckedProp = elementProps.find((p) => isExactKey(p.key, "checked"));
474
+ const authorValueProp = keepStaticValue ? void 0 : elementProps.find((p) => isExactKey(p.key, "value"));
473
475
  removePropsByName(props, keepStaticValue ? ["checked"] : ["checked", "value"]);
474
476
  const registerValueArr = Array.isArray(registerSummarizedProp2.value) ? registerSummarizedProp2.value : [registerSummarizedProp2.value];
475
- const valueExpression = createCompoundExpression([
476
- "(",
477
- ...registerValueArr,
478
- ")?.displayValue?.value"
479
- ]);
477
+ const authorValueArr = toExpressionArray(authorValueProp?.value);
478
+ const valueExpression = createCompoundExpression(
479
+ authorValueArr === void 0 ? ["(", ...registerValueArr, ")?.displayValue?.value"] : ["((", ...registerValueArr, ")?.displayValue?.value ?? (", ...authorValueArr, "))"]
480
+ );
480
481
  const trueValueIndex = elementProps.findIndex((p) => isExactKey(p.key, "true-value"));
481
482
  const trueValueProp = elementProps[trueValueIndex];
482
483
  const scalarTarget = isStaticCheckbox ? trueValueProp !== void 0 ? trueValueProp.value : "true" : elementValueSummarizedProp2.value;
483
- const coreExpression = [
484
- "(",
485
- ...elementSelectionLabelExpression.children,
486
- ") === 'checked' ? (",
487
- // resolves to a boolean
484
+ const authorCheckedArr = toExpressionArray(authorCheckedProp?.value);
485
+ const checkedExpression = authorCheckedArr === void 0 ? generateEqualityExpression(
486
+ registerSummarizedProp2.value,
487
+ elementValueSummarizedProp2.value,
488
+ scalarTarget
489
+ ) : [
490
+ "((",
491
+ ...registerValueArr,
492
+ ") == null ? (",
493
+ ...authorCheckedArr,
494
+ ") : (",
488
495
  ...generateEqualityExpression(
489
496
  registerSummarizedProp2.value,
490
497
  elementValueSummarizedProp2.value,
491
498
  scalarTarget
492
499
  ),
500
+ "))"
501
+ ];
502
+ const coreExpression = [
503
+ "(",
504
+ ...elementSelectionLabelExpression.children,
505
+ ") === 'checked' ? (",
506
+ // resolves to a boolean
507
+ ...checkedExpression,
493
508
  ") : (",
494
509
  // resolves to the provided register value
495
510
  ...valueExpression.children,
@@ -562,22 +577,10 @@ const inputTextAreaNodeTransform = (node) => {
562
577
  }
563
578
  };
564
579
 
565
- const RECURSABLE_NODE_TYPES = /* @__PURE__ */ new Set([
566
- NodeTypes.ELEMENT,
567
- NodeTypes.FOR,
568
- NodeTypes.IF,
569
- NodeTypes.IF_BRANCH
570
- ]);
571
- function findRedundantStateBinding(props, stateNames) {
580
+ function findRedundantStateBinding(props) {
572
581
  for (const prop of props) {
573
- if (prop.type === NodeTypes.ATTRIBUTE) {
574
- if (stateNames.includes(prop.name)) return prop.name;
575
- continue;
576
- }
582
+ if (prop.type === NodeTypes.ATTRIBUTE) continue;
577
583
  if (prop.name === "model") return "v-model";
578
- if (prop.name === "bind" && prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION && prop.arg.isStatic && stateNames.includes(prop.arg.content)) {
579
- return `:${prop.arg.content}`;
580
- }
581
584
  }
582
585
  return null;
583
586
  }
@@ -602,42 +605,23 @@ function emitRedundantWarning(tag, binding) {
602
605
  `[attaform] \`${binding}\` is redundant beside v-register on <${tag}>. v-register already drives this field's value, so keep v-register alone and drop \`${binding}\`. (An identity \`:value\` on a radio or <option> is expected and stays silent.)`
603
606
  );
604
607
  }
605
- function walkOptionsForSelected(selectNode) {
606
- const visit = (candidate) => {
607
- if (candidate.type === NodeTypes.ELEMENT && candidate.tag === "option") {
608
- const found = findRedundantStateBinding(candidate.props, ["selected"]);
609
- if (found !== null) emitRedundantWarning("option", found);
610
- return;
611
- }
612
- if (!RECURSABLE_NODE_TYPES.has(candidate.type)) return;
613
- if (!("children" in candidate)) return;
614
- for (const child of candidate.children) {
615
- if (typeof child === "string" || typeof child === "symbol") continue;
616
- if (child.type === NodeTypes.SIMPLE_EXPRESSION) continue;
617
- visit(child);
618
- }
619
- };
620
- for (const child of selectNode.children) visit(child);
621
- }
622
608
  function warnIfRedundant(node) {
623
609
  if (node.tagType !== ElementTypes.ELEMENT) return;
624
610
  const tag = node.tag;
625
611
  if (tag === "select") {
626
- const found2 = findRedundantStateBinding(node.props, ["value"]);
612
+ const found2 = findRedundantStateBinding(node.props);
627
613
  if (found2 !== null) emitRedundantWarning("select", found2);
628
- walkOptionsForSelected(node);
629
614
  return;
630
615
  }
631
616
  if (tag === "textarea") {
632
- const found2 = findRedundantStateBinding(node.props, ["value"]);
617
+ const found2 = findRedundantStateBinding(node.props);
633
618
  if (found2 !== null) emitRedundantWarning("textarea", found2);
634
619
  return;
635
620
  }
636
621
  if (tag !== "input") return;
637
622
  const kind = classifyInput(node.props);
638
623
  if (kind === "dynamic" || kind === "file") return;
639
- const stateNames = kind === "checkbox" || kind === "radio" ? ["checked"] : ["value"];
640
- const found = findRedundantStateBinding(node.props, stateNames);
624
+ const found = findRedundantStateBinding(node.props);
641
625
  if (found !== null) emitRedundantWarning("input", found);
642
626
  }
643
627
  const redundantBindingWarnTransform = (node) => {
@@ -1,7 +1,7 @@
1
- import { a as InvalidUseFormConfigError } from './attaform.wfY8XFvm.mjs';
2
- import { u as useForm$2 } from './attaform.CJP3RkGa.mjs';
3
- import { u as useForm$1 } from './attaform.NLmerepI.mjs';
4
- import { i as installingFieldMetaStore, g as getFieldMetaForSchema } from './attaform.C09fpdLS.mjs';
1
+ import { a as InvalidUseFormConfigError } from './attaform.CZYt_5N_.mjs';
2
+ import { u as useForm$2 } from './attaform.D1fnTifF.mjs';
3
+ import { u as useForm$1 } from './attaform.C2MVyuxC.mjs';
4
+ import { i as installingFieldMetaStore, g as getFieldMetaForSchema } from './attaform.B0dKL8ST.mjs';
5
5
 
6
6
  function isZodV4SchemaShape(value) {
7
7
  if (typeof value !== "object" || value === null) return false;
@@ -24,6 +24,14 @@ function canonicalStringify(value, seen = /* @__PURE__ */ new WeakSet()) {
24
24
  try {
25
25
  if (value instanceof Date) return `date:${value.getTime()}`;
26
26
  if (value instanceof RegExp) return `regex:${String(value)}`;
27
+ if (value instanceof Map) {
28
+ const entries2 = [...value].map(([k, v]) => `${canonicalStringify(k, seen)}=>${canonicalStringify(v, seen)}`).sort();
29
+ return `map:[${entries2.join(",")}]`;
30
+ }
31
+ if (value instanceof Set) {
32
+ const members = [...value].map((v) => canonicalStringify(v, seen)).sort();
33
+ return `set:[${members.join(",")}]`;
34
+ }
27
35
  const entries = Object.entries(obj).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonicalStringify(v, seen)}`);
28
36
  return `{${entries.join(",")}}`;
29
37
  } finally {
@@ -1,30 +1,9 @@
1
- import { o as humanize, h as useAbstractForm } from './attaform.B8k8JrmK.mjs';
2
- import { A as AttaformError, e as canonicalizePath, a as InvalidUseFormConfigError } from './attaform.wfY8XFvm.mjs';
3
- import { s as slimPrimitivesWalk, d as deriveDefaultWalk, m as mergeDeep, f as fixStructuralDefaults, w as walkPathSegments, c as createAbstractSchema, b as buildFieldMetaPathMap, a as getFieldMetaListForSchema, g as getFieldMetaForSchema } from './attaform.C09fpdLS.mjs';
1
+ import { q as humanize, h as useAbstractForm } from './attaform.CZMAYwSK.mjs';
2
+ import { A as AttaformError, e as canonicalizePath, a as InvalidUseFormConfigError } from './attaform.CZYt_5N_.mjs';
3
+ import { s as slimPrimitivesWalk, d as deriveDefaultWalk, m as mergeDeep, f as fixStructuralDefaults, w as walkPathSegments, c as createAbstractSchema, b as buildFieldMetaPathMap, a as getFieldMetaListForSchema, g as getFieldMetaForSchema } from './attaform.B0dKL8ST.mjs';
4
+ import { c as callConsumerSchemaFn } from './attaform.Cvao8bW5.mjs';
4
5
  import { z } from 'zod';
5
6
 
6
- function zodIssuesToValidationErrors(issues) {
7
- return issues.map((issue) => {
8
- let code;
9
- if (typeof issue.code === "string" && issue.code.length > 0) {
10
- code = `zod:${issue.code}`;
11
- } else {
12
- code = "zod:unknown";
13
- }
14
- return {
15
- message: issue.message,
16
- // Adapter-side paths stay schema-relative — the validation
17
- // pipeline in `create-form-store.ts` prepends the parent path
18
- // to absolutise, then routes form-level (absolute path length 0)
19
- // entries to the empty-string bucket at storage time.
20
- path: issue.path.map((seg) => typeof seg === "number" ? seg : String(seg)),
21
- code
22
- };
23
- });
24
- }
25
- class UnsupportedSchemaError extends AttaformError {
26
- }
27
-
28
7
  function readDef(schema) {
29
8
  if (schema === null || typeof schema !== "object") return void 0;
30
9
  return schema.def;
@@ -103,6 +82,8 @@ function getRecordValueType(schema) {
103
82
  const def = readDef(schema);
104
83
  return def?.valueType;
105
84
  }
85
+ const getMapKeyType = getRecordKeyType;
86
+ const getMapValueType = getRecordValueType;
106
87
  function getTupleItems(schema) {
107
88
  const def = readDef(schema);
108
89
  return def?.items ?? [];
@@ -149,7 +130,7 @@ function unwrapLazy(schema) {
149
130
  const def = readDef(schema);
150
131
  const getter = def?.getter;
151
132
  if (typeof getter !== "function") return void 0;
152
- return getter();
133
+ return callConsumerSchemaFn(() => getter(), void 0);
153
134
  }
154
135
  function getLazyGetter(schema) {
155
136
  const def = readDef(schema);
@@ -167,11 +148,9 @@ function getCatchDefault(schema) {
167
148
  const def = readDef(schema);
168
149
  const cv = def?.catchValue;
169
150
  if (typeof cv !== "function") return void 0;
170
- try {
171
- return cv({ error: new Error("atta:default-values"), input: void 0 });
172
- } catch {
173
- return void 0;
174
- }
151
+ return callConsumerSchemaFn(
152
+ () => cv({ error: new Error("atta:default-values"), input: void 0 }),
153
+ void 0);
175
154
  }
176
155
  function hasCatchValue(schema) {
177
156
  const def = readDef(schema);
@@ -179,7 +158,7 @@ function hasCatchValue(schema) {
179
158
  }
180
159
  function getDefaultValue(schema) {
181
160
  const def = readDef(schema);
182
- return def?.defaultValue;
161
+ return callConsumerSchemaFn(() => def?.defaultValue, void 0);
183
162
  }
184
163
  function getNativeEnumValues(_schema) {
185
164
  return void 0;
@@ -328,123 +307,6 @@ function isAsyncCheck(check) {
328
307
  return fn.constructor.name === "AsyncFunction";
329
308
  }
330
309
 
331
- const UNSUPPORTED = [
332
- "promise",
333
- "custom",
334
- "template-literal",
335
- "map",
336
- "symbol",
337
- "function"
338
- ];
339
- function labelPath(path) {
340
- return path.length === 0 ? "<root>" : path.join(".");
341
- }
342
- function assertSupportedKinds(schema, path = [], lazyGetters = []) {
343
- const kind = kindOf(schema);
344
- if (UNSUPPORTED.includes(kind)) {
345
- throw new UnsupportedSchemaError(
346
- `[attaform] AF02 attaform.dev/e/af02 '${kind}' at '${labelPath(path)}'`
347
- );
348
- }
349
- switch (kind) {
350
- case "object": {
351
- const shape = getObjectShape(schema);
352
- for (const [key, sub] of Object.entries(shape)) {
353
- assertSupportedKinds(sub, [...path, key], lazyGetters);
354
- }
355
- return;
356
- }
357
- case "array":
358
- assertSupportedKinds(getArrayElement(schema), [...path, "*"], lazyGetters);
359
- return;
360
- case "set":
361
- assertSupportedKinds(getSetValueType(schema), [...path, "*"], lazyGetters);
362
- return;
363
- case "record":
364
- assertSupportedKinds(getRecordValueType(schema), [...path, "*"], lazyGetters);
365
- return;
366
- case "tuple": {
367
- const items = getTupleItems(schema);
368
- items.forEach((item, i) => assertSupportedKinds(item, [...path, String(i)], lazyGetters));
369
- return;
370
- }
371
- case "union": {
372
- const options = getUnionOptions(schema);
373
- options.forEach((opt, i) => assertSupportedKinds(opt, [...path, `|${i}`], lazyGetters));
374
- return;
375
- }
376
- case "discriminated-union": {
377
- const options = getDiscriminatedOptions(schema);
378
- options.forEach((opt, i) => assertSupportedKinds(opt, [...path, `|${i}`], lazyGetters));
379
- return;
380
- }
381
- case "optional":
382
- case "nullable":
383
- case "default":
384
- case "readonly":
385
- case "catch": {
386
- const inner = unwrapInner(schema);
387
- if (inner !== void 0) assertSupportedKinds(inner, path, lazyGetters);
388
- return;
389
- }
390
- case "pipe": {
391
- const inner = unwrapPipe(schema);
392
- if (inner !== void 0) assertSupportedKinds(inner, path, lazyGetters);
393
- return;
394
- }
395
- case "lazy": {
396
- const getter = getLazyGetter(schema);
397
- if (getter !== void 0 && lazyGetters.includes(getter)) return;
398
- const inner = unwrapLazy(schema);
399
- if (inner !== void 0) {
400
- assertSupportedKinds(
401
- inner,
402
- path,
403
- getter === void 0 ? lazyGetters : [...lazyGetters, getter]
404
- );
405
- }
406
- return;
407
- }
408
- case "intersection": {
409
- const left = getIntersectionLeft(schema);
410
- const right = getIntersectionRight(schema);
411
- if (left !== void 0) assertSupportedKinds(left, [...path, "left"], lazyGetters);
412
- if (right !== void 0) assertSupportedKinds(right, [...path, "right"], lazyGetters);
413
- return;
414
- }
415
- // Leaves: nothing to descend into.
416
- case "string":
417
- case "number":
418
- case "boolean":
419
- case "bigint":
420
- case "date":
421
- case "enum":
422
- case "literal":
423
- case "null":
424
- case "undefined":
425
- case "nan":
426
- case "any":
427
- case "unknown":
428
- case "void":
429
- case "never":
430
- case "promise":
431
- case "custom":
432
- case "template-literal":
433
- case "transform":
434
- case "file":
435
- case "map":
436
- case "symbol":
437
- case "function":
438
- return;
439
- default: {
440
- const _exhaustive = kind;
441
- throw new Error(
442
- `[attaform] AF03 attaform.dev/e/af03 '${_exhaustive}'`
443
- );
444
- }
445
- }
446
- }
447
-
448
310
  function unwrapToDiscriminatedUnion(schema) {
449
311
  let current = schema;
450
312
  for (let i = 0; i < 64; i++) {
@@ -471,6 +333,26 @@ function unwrapToDiscriminatedUnion(schema) {
471
333
  return void 0;
472
334
  }
473
335
 
336
+ function zodIssuesToValidationErrors(issues) {
337
+ return issues.map((issue) => {
338
+ let code;
339
+ if (typeof issue.code === "string" && issue.code.length > 0) {
340
+ code = `zod:${issue.code}`;
341
+ } else {
342
+ code = "zod:unknown";
343
+ }
344
+ return {
345
+ message: issue.message,
346
+ // Adapter-side paths stay schema-relative — the validation
347
+ // pipeline in `create-form-store.ts` prepends the parent path
348
+ // to absolutise, then routes form-level (absolute path length 0)
349
+ // entries to the empty-string bucket at storage time.
350
+ path: issue.path.map((seg) => typeof seg === "number" ? seg : String(seg)),
351
+ code
352
+ };
353
+ });
354
+ }
355
+
474
356
  const V4_INTROSPECTOR = {
475
357
  kindOf: (schema) => kindOf(schema),
476
358
  getObjectShape: (schema) => getObjectShape(schema),
@@ -492,6 +374,8 @@ const V4_INTROSPECTOR = {
492
374
  getSetValueType: (schema) => kindOf(schema) === "set" ? getSetValueType(schema) : void 0,
493
375
  getRecordKeyType: (schema) => kindOf(schema) === "record" ? getRecordKeyType(schema) : void 0,
494
376
  getRecordValueType: (schema) => kindOf(schema) === "record" ? getRecordValueType(schema) : void 0,
377
+ getMapKeyType: (schema) => kindOf(schema) === "map" ? getMapKeyType(schema) : void 0,
378
+ getMapValueType: (schema) => kindOf(schema) === "map" ? getMapValueType(schema) : void 0,
495
379
  getUnionOptions,
496
380
  getIntersectionLeft,
497
381
  getIntersectionRight,
@@ -697,6 +581,13 @@ function unwrapStructuralWrappers(schema) {
697
581
  }
698
582
  return current;
699
583
  }
584
+ function assertKeyedRoot(rootSchema) {
585
+ const kind = kindOf(peelAllWrappers(rootSchema));
586
+ if (kind === "object" || kind === "record" || kind === "discriminated-union") return;
587
+ throw new AttaformError(
588
+ `[attaform] AF15 attaform.dev/e/af15 '${kind}'`
589
+ );
590
+ }
700
591
  function peelAllWrappers(schema) {
701
592
  let current = schema;
702
593
  for (let i = 0; i < 64; i++) {
@@ -770,7 +661,7 @@ function isLeafRequired(schema, depth = 0) {
770
661
  }
771
662
  function zodV4Adapter(rootSchema) {
772
663
  assertZodVersion(rootSchema);
773
- assertSupportedKinds(rootSchema);
664
+ assertKeyedRoot(rootSchema);
774
665
  return (formKey, options) => createAbstractSchema(
775
666
  rootSchema,
776
667
  V4_INTROSPECTOR,
@@ -917,4 +808,4 @@ function useForm(configuration) {
917
808
  });
918
809
  }
919
810
 
920
- export { UnsupportedSchemaError as U, assertZodVersion as a, getIntersectionRight as b, unwrapLazy as c, unwrapInner as d, unwrapPipe as e, getDiscriminator as f, getIntersectionLeft as g, getDiscriminatedOptions as h, getUnionOptions as i, getRecordKeyType as j, kindOf as k, getRecordValueType as l, getTupleItems as m, getSetValueType as n, getArrayElement as o, getObjectShape as p, getEnumValues as q, getLiteralValues as r, getChecks as s, getCatchDefault as t, useForm as u, getDefaultValue as v, zodV4Adapter as z };
811
+ export { assertZodVersion as a, getIntersectionRight as b, unwrapLazy as c, unwrapInner as d, unwrapPipe as e, getDiscriminator as f, getIntersectionLeft as g, getDiscriminatedOptions as h, getUnionOptions as i, getRecordKeyType as j, kindOf as k, getRecordValueType as l, getTupleItems as m, getSetValueType as n, getArrayElement as o, getObjectShape as p, getEnumValues as q, getLiteralValues as r, getChecks as s, getCatchDefault as t, useForm as u, getDefaultValue as v, zodV4Adapter as z };