@flanksource/clicky-ui 0.2.8 → 0.2.10

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 (139) hide show
  1. package/dist/components/Combobox.cjs +89 -49
  2. package/dist/components/Combobox.cjs.map +1 -1
  3. package/dist/components/Combobox.d.ts +3 -0
  4. package/dist/components/Combobox.d.ts.map +1 -1
  5. package/dist/components/Combobox.js +91 -51
  6. package/dist/components/Combobox.js.map +1 -1
  7. package/dist/components/FilterBar.cjs +42 -44
  8. package/dist/components/FilterBar.cjs.map +1 -1
  9. package/dist/components/FilterBar.d.ts +19 -0
  10. package/dist/components/FilterBar.d.ts.map +1 -1
  11. package/dist/components/FilterBar.js +43 -45
  12. package/dist/components/FilterBar.js.map +1 -1
  13. package/dist/components/JsonSchemaForm.cjs +48 -0
  14. package/dist/components/JsonSchemaForm.cjs.map +1 -0
  15. package/dist/components/JsonSchemaForm.d.ts +3 -0
  16. package/dist/components/JsonSchemaForm.d.ts.map +1 -0
  17. package/dist/components/JsonSchemaForm.js +48 -0
  18. package/dist/components/JsonSchemaForm.js.map +1 -0
  19. package/dist/components/json-schema-form-array.cjs +169 -0
  20. package/dist/components/json-schema-form-array.cjs.map +1 -0
  21. package/dist/components/json-schema-form-array.d.ts +8 -0
  22. package/dist/components/json-schema-form-array.d.ts.map +1 -0
  23. package/dist/components/json-schema-form-array.js +169 -0
  24. package/dist/components/json-schema-form-array.js.map +1 -0
  25. package/dist/components/json-schema-form-fields.cjs +374 -0
  26. package/dist/components/json-schema-form-fields.cjs.map +1 -0
  27. package/dist/components/json-schema-form-fields.d.ts +19 -0
  28. package/dist/components/json-schema-form-fields.d.ts.map +1 -0
  29. package/dist/components/json-schema-form-fields.js +374 -0
  30. package/dist/components/json-schema-form-fields.js.map +1 -0
  31. package/dist/components/json-schema-form-render.cjs +154 -0
  32. package/dist/components/json-schema-form-render.cjs.map +1 -0
  33. package/dist/components/json-schema-form-render.d.ts +40 -0
  34. package/dist/components/json-schema-form-render.d.ts.map +1 -0
  35. package/dist/components/json-schema-form-render.js +154 -0
  36. package/dist/components/json-schema-form-render.js.map +1 -0
  37. package/dist/components/json-schema-form-resolve.cjs +121 -0
  38. package/dist/components/json-schema-form-resolve.cjs.map +1 -0
  39. package/dist/components/json-schema-form-resolve.d.ts +19 -0
  40. package/dist/components/json-schema-form-resolve.d.ts.map +1 -0
  41. package/dist/components/json-schema-form-resolve.js +121 -0
  42. package/dist/components/json-schema-form-resolve.js.map +1 -0
  43. package/dist/components/json-schema-form-types.d.ts +124 -0
  44. package/dist/components/json-schema-form-types.d.ts.map +1 -0
  45. package/dist/components.cjs +7 -0
  46. package/dist/components.cjs.map +1 -1
  47. package/dist/components.d.ts +3 -0
  48. package/dist/components.d.ts.map +1 -1
  49. package/dist/components.js +8 -1
  50. package/dist/components.js.map +1 -1
  51. package/dist/data/Clicky.cjs +1 -1
  52. package/dist/data/Clicky.cjs.map +1 -1
  53. package/dist/data/Clicky.js +1 -1
  54. package/dist/data/Clicky.js.map +1 -1
  55. package/dist/data/DataTable.cjs +16 -15
  56. package/dist/data/DataTable.cjs.map +1 -1
  57. package/dist/data/DataTable.d.ts +2 -1
  58. package/dist/data/DataTable.d.ts.map +1 -1
  59. package/dist/data/DataTable.js +16 -15
  60. package/dist/data/DataTable.js.map +1 -1
  61. package/dist/data/Icon.cjs +11 -0
  62. package/dist/data/Icon.cjs.map +1 -1
  63. package/dist/data/Icon.d.ts +12 -1
  64. package/dist/data/Icon.d.ts.map +1 -1
  65. package/dist/data/Icon.js +12 -1
  66. package/dist/data/Icon.js.map +1 -1
  67. package/dist/data/LogDetails.cjs +277 -0
  68. package/dist/data/LogDetails.cjs.map +1 -0
  69. package/dist/data/LogDetails.d.ts +5 -0
  70. package/dist/data/LogDetails.d.ts.map +1 -0
  71. package/dist/data/LogDetails.js +277 -0
  72. package/dist/data/LogDetails.js.map +1 -0
  73. package/dist/data/LogsTable.cjs +6 -202
  74. package/dist/data/LogsTable.cjs.map +1 -1
  75. package/dist/data/LogsTable.d.ts.map +1 -1
  76. package/dist/data/LogsTable.js +4 -200
  77. package/dist/data/LogsTable.js.map +1 -1
  78. package/dist/data/Properties.cjs +2 -2
  79. package/dist/data/Properties.cjs.map +1 -1
  80. package/dist/data/Properties.js +2 -2
  81. package/dist/data/Properties.js.map +1 -1
  82. package/dist/data/cells/TagList.cjs +19 -3
  83. package/dist/data/cells/TagList.cjs.map +1 -1
  84. package/dist/data/cells/TagList.d.ts +11 -1
  85. package/dist/data/cells/TagList.d.ts.map +1 -1
  86. package/dist/data/cells/TagList.js +19 -3
  87. package/dist/data/cells/TagList.js.map +1 -1
  88. package/dist/data/cells/Timestamp.cjs +17 -2
  89. package/dist/data/cells/Timestamp.cjs.map +1 -1
  90. package/dist/data/cells/Timestamp.d.ts +2 -0
  91. package/dist/data/cells/Timestamp.d.ts.map +1 -1
  92. package/dist/data/cells/Timestamp.js +17 -2
  93. package/dist/data/cells/Timestamp.js.map +1 -1
  94. package/dist/data/log-utils.cjs +7 -0
  95. package/dist/data/log-utils.cjs.map +1 -0
  96. package/dist/data/log-utils.d.ts +2 -0
  97. package/dist/data/log-utils.d.ts.map +1 -0
  98. package/dist/data/log-utils.js +7 -0
  99. package/dist/data/log-utils.js.map +1 -0
  100. package/dist/data.cjs +3 -0
  101. package/dist/data.cjs.map +1 -1
  102. package/dist/data.d.ts +2 -2
  103. package/dist/data.d.ts.map +1 -1
  104. package/dist/data.js +5 -2
  105. package/dist/index.cjs +13 -0
  106. package/dist/index.cjs.map +1 -1
  107. package/dist/index.js +15 -2
  108. package/dist/index.js.map +1 -1
  109. package/dist/rpc/EntityExplorerApp.cjs +3 -2
  110. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  111. package/dist/rpc/EntityExplorerApp.js +3 -2
  112. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  113. package/dist/rpc/OperationActionDialog.cjs +1 -1
  114. package/dist/rpc/OperationActionDialog.cjs.map +1 -1
  115. package/dist/rpc/OperationActionDialog.js +1 -1
  116. package/dist/rpc/OperationActionDialog.js.map +1 -1
  117. package/dist/rpc/OperationCommandPage.cjs +21 -14
  118. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  119. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  120. package/dist/rpc/OperationCommandPage.js +21 -14
  121. package/dist/rpc/OperationCommandPage.js.map +1 -1
  122. package/dist/rpc/apiClient.cjs +316 -0
  123. package/dist/rpc/apiClient.cjs.map +1 -0
  124. package/dist/rpc/apiClient.d.ts +44 -0
  125. package/dist/rpc/apiClient.d.ts.map +1 -0
  126. package/dist/rpc/apiClient.js +316 -0
  127. package/dist/rpc/apiClient.js.map +1 -0
  128. package/dist/rpc/useOperations.cjs.map +1 -1
  129. package/dist/rpc/useOperations.d.ts +2 -1
  130. package/dist/rpc/useOperations.d.ts.map +1 -1
  131. package/dist/rpc/useOperations.js.map +1 -1
  132. package/dist/rpc.cjs +3 -0
  133. package/dist/rpc.cjs.map +1 -1
  134. package/dist/rpc.d.ts +1 -0
  135. package/dist/rpc.d.ts.map +1 -1
  136. package/dist/rpc.js +3 -0
  137. package/dist/rpc.js.map +1 -1
  138. package/dist/styles.css +1 -1
  139. package/package.json +1 -1
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const utils = require("../lib/utils.cjs");
5
+ const jsonSchemaFormRender = require("./json-schema-form-render.cjs");
6
+ const DEFAULT_LABEL_MAX_WIDTH = "40ch";
7
+ const DEFAULT_VALUE_MAX_WIDTH = "400px";
8
+ function resolveFormLayout(layout, inline) {
9
+ const base = layout ?? { mode: inline ? "inline" : "stacked" };
10
+ if (base.mode !== "inline") return { mode: "stacked" };
11
+ return {
12
+ mode: "inline",
13
+ labelMaxWidth: base.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,
14
+ valueMaxWidth: base.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH
15
+ };
16
+ }
17
+ function JsonSchemaForm({
18
+ schema,
19
+ value,
20
+ onChange,
21
+ readOnly = false,
22
+ inline = false,
23
+ layout,
24
+ hideReadOnlyFields = false,
25
+ hiddenKeys,
26
+ requiredFirst = false,
27
+ title,
28
+ pre,
29
+ post
30
+ }) {
31
+ const resolvedLayout = resolveFormLayout(layout, inline);
32
+ const ctx = {
33
+ readOnly,
34
+ hideReadOnlyFields,
35
+ layout: resolvedLayout,
36
+ requiredFirst,
37
+ pre: pre ?? [],
38
+ post: post ?? [],
39
+ depth: 0
40
+ };
41
+ const rows = jsonSchemaFormRender.renderObjectFields(schema, value, onChange, ctx, hiddenKeys ? { hiddenKeys } : void 0);
42
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
43
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: title }),
44
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn(resolvedLayout.mode === "inline" ? "grid gap-2" : "grid gap-4"), children: rows })
45
+ ] });
46
+ }
47
+ exports.JsonSchemaForm = JsonSchemaForm;
48
+ //# sourceMappingURL=JsonSchemaForm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSchemaForm.cjs","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\nimport { renderObjectFields, type RenderContext } from \"./json-schema-form-render\";\nimport type { FormLayout, JsonSchemaFormProps } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"400px\";\n\n// resolveFormLayout maps the `layout`/`inline` props to a single resolved\n// FormLayout. An explicit `layout` wins; otherwise `inline` selects the inline\n// preset. Width caps are only filled for inline mode.\nfunction resolveFormLayout(layout: FormLayout | undefined, inline: boolean): FormLayout {\n const base = layout ?? { mode: inline ? \"inline\" : \"stacked\" };\n if (base.mode !== \"inline\") return { mode: \"stacked\" };\n return {\n mode: \"inline\",\n labelMaxWidth: base.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth: base.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n readOnly = false,\n inline = false,\n layout,\n hideReadOnlyFields = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n}: JsonSchemaFormProps) {\n const resolvedLayout = resolveFormLayout(layout, inline);\n const ctx: RenderContext = {\n readOnly,\n hideReadOnlyFields,\n layout: resolvedLayout,\n requiredFirst,\n pre: pre ?? [],\n post: post ?? [],\n depth: 0,\n };\n const rows = renderObjectFields(schema, value, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n\n return (\n <div className=\"space-y-3\">\n {title && <h3 className=\"text-sm font-semibold\">{title}</h3>}\n <div className={cn(resolvedLayout.mode === \"inline\" ? \"grid gap-2\" : \"grid gap-4\")}>{rows}</div>\n </div>\n );\n}\n"],"names":["renderObjectFields","jsxs","jsx","cn"],"mappings":";;;;;AAIA,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAKhC,SAAS,kBAAkB,QAAgC,QAA6B;AACtF,QAAM,OAAO,UAAU,EAAE,MAAM,SAAS,WAAW,UAAA;AACnD,MAAI,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAA;AAC3C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe,KAAK,iBAAiB;AAAA,IACrC,eAAe,KAAK,iBAAiB;AAAA,EAAA;AAEzC;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,iBAAiB,kBAAkB,QAAQ,MAAM;AACvD,QAAM,MAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,KAAK,OAAO,CAAA;AAAA,IACZ,MAAM,QAAQ,CAAA;AAAA,IACd,OAAO;AAAA,EAAA;AAET,QAAM,OAAOA,qBAAAA,mBAAmB,QAAQ,OAAO,UAAU,KAAK,aAAa,EAAE,WAAA,IAAe,MAAS;AAErG,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,SAASC,2BAAAA,IAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,OAAM;AAAA,IACvDA,2BAAAA,IAAC,OAAA,EAAI,WAAWC,MAAAA,GAAG,eAAe,SAAS,WAAW,eAAe,YAAY,GAAI,UAAA,KAAA,CAAK;AAAA,EAAA,GAC5F;AAEJ;;"}
@@ -0,0 +1,3 @@
1
+ import { JsonSchemaFormProps } from './json-schema-form-types';
2
+ export declare function JsonSchemaForm({ schema, value, onChange, readOnly, inline, layout, hideReadOnlyFields, hiddenKeys, requiredFirst, title, pre, post, }: JsonSchemaFormProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=JsonSchemaForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSchemaForm.d.ts","sourceRoot":"","sources":["../../src/components/JsonSchemaForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAuBhF,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,MAAc,EACd,MAAM,EACN,kBAA0B,EAC1B,UAAU,EACV,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,IAAI,GACL,EAAE,mBAAmB,2CAmBrB"}
@@ -0,0 +1,48 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ import { renderObjectFields } from "./json-schema-form-render.js";
4
+ const DEFAULT_LABEL_MAX_WIDTH = "40ch";
5
+ const DEFAULT_VALUE_MAX_WIDTH = "400px";
6
+ function resolveFormLayout(layout, inline) {
7
+ const base = layout ?? { mode: inline ? "inline" : "stacked" };
8
+ if (base.mode !== "inline") return { mode: "stacked" };
9
+ return {
10
+ mode: "inline",
11
+ labelMaxWidth: base.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,
12
+ valueMaxWidth: base.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH
13
+ };
14
+ }
15
+ function JsonSchemaForm({
16
+ schema,
17
+ value,
18
+ onChange,
19
+ readOnly = false,
20
+ inline = false,
21
+ layout,
22
+ hideReadOnlyFields = false,
23
+ hiddenKeys,
24
+ requiredFirst = false,
25
+ title,
26
+ pre,
27
+ post
28
+ }) {
29
+ const resolvedLayout = resolveFormLayout(layout, inline);
30
+ const ctx = {
31
+ readOnly,
32
+ hideReadOnlyFields,
33
+ layout: resolvedLayout,
34
+ requiredFirst,
35
+ pre: pre ?? [],
36
+ post: post ?? [],
37
+ depth: 0
38
+ };
39
+ const rows = renderObjectFields(schema, value, onChange, ctx, hiddenKeys ? { hiddenKeys } : void 0);
40
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
41
+ title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: title }),
42
+ /* @__PURE__ */ jsx("div", { className: cn(resolvedLayout.mode === "inline" ? "grid gap-2" : "grid gap-4"), children: rows })
43
+ ] });
44
+ }
45
+ export {
46
+ JsonSchemaForm
47
+ };
48
+ //# sourceMappingURL=JsonSchemaForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSchemaForm.js","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\nimport { renderObjectFields, type RenderContext } from \"./json-schema-form-render\";\nimport type { FormLayout, JsonSchemaFormProps } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"400px\";\n\n// resolveFormLayout maps the `layout`/`inline` props to a single resolved\n// FormLayout. An explicit `layout` wins; otherwise `inline` selects the inline\n// preset. Width caps are only filled for inline mode.\nfunction resolveFormLayout(layout: FormLayout | undefined, inline: boolean): FormLayout {\n const base = layout ?? { mode: inline ? \"inline\" : \"stacked\" };\n if (base.mode !== \"inline\") return { mode: \"stacked\" };\n return {\n mode: \"inline\",\n labelMaxWidth: base.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth: base.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n readOnly = false,\n inline = false,\n layout,\n hideReadOnlyFields = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n}: JsonSchemaFormProps) {\n const resolvedLayout = resolveFormLayout(layout, inline);\n const ctx: RenderContext = {\n readOnly,\n hideReadOnlyFields,\n layout: resolvedLayout,\n requiredFirst,\n pre: pre ?? [],\n post: post ?? [],\n depth: 0,\n };\n const rows = renderObjectFields(schema, value, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n\n return (\n <div className=\"space-y-3\">\n {title && <h3 className=\"text-sm font-semibold\">{title}</h3>}\n <div className={cn(resolvedLayout.mode === \"inline\" ? \"grid gap-2\" : \"grid gap-4\")}>{rows}</div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;AAIA,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAKhC,SAAS,kBAAkB,QAAgC,QAA6B;AACtF,QAAM,OAAO,UAAU,EAAE,MAAM,SAAS,WAAW,UAAA;AACnD,MAAI,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAA;AAC3C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe,KAAK,iBAAiB;AAAA,IACrC,eAAe,KAAK,iBAAiB;AAAA,EAAA;AAEzC;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,iBAAiB,kBAAkB,QAAQ,MAAM;AACvD,QAAM,MAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,KAAK,OAAO,CAAA;AAAA,IACZ,MAAM,QAAQ,CAAA;AAAA,IACd,OAAO;AAAA,EAAA;AAET,QAAM,OAAO,mBAAmB,QAAQ,OAAO,UAAU,KAAK,aAAa,EAAE,WAAA,IAAe,MAAS;AAErG,SACE,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,SAAS,oBAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,OAAM;AAAA,IACvD,oBAAC,OAAA,EAAI,WAAW,GAAG,eAAe,SAAS,WAAW,eAAe,YAAY,GAAI,UAAA,KAAA,CAAK;AAAA,EAAA,GAC5F;AAEJ;"}
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ require("react");
5
+ const Icon = require("../data/Icon.cjs");
6
+ const button = require("./button.cjs");
7
+ const jsonSchemaFormFields = require("./json-schema-form-fields.cjs");
8
+ const jsonSchemaFormResolve = require("./json-schema-form-resolve.cjs");
9
+ const jsonSchemaFormRender = require("./json-schema-form-render.cjs");
10
+ const UiAdd = require("../icons/components/UiAdd.cjs");
11
+ const UiClose = require("../icons/components/UiClose.cjs");
12
+ const UiChevronUp = require("../icons/components/UiChevronUp.cjs");
13
+ const UiChevronDown = require("../icons/components/UiChevronDown.cjs");
14
+ const UiTrash = require("../icons/components/UiTrash.cjs");
15
+ function ArrayControl({
16
+ field,
17
+ fieldId,
18
+ ctx
19
+ }) {
20
+ const readOnly = ctx.readOnly || field.readOnly === true;
21
+ if (jsonSchemaFormResolve.isScalarStringItems(field.itemSchema)) {
22
+ return /* @__PURE__ */ jsxRuntime.jsx(TagArray, { field, fieldId, readOnly });
23
+ }
24
+ const items = Array.isArray(field.value) ? field.value : [];
25
+ const itemSchema = field.itemSchema ?? { type: "string" };
26
+ const childCtx = { ...ctx, readOnly, depth: ctx.depth + 1 };
27
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 rounded-md border border-input p-2", children: [
28
+ items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_auto] items-start gap-2", children: [
29
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: jsonSchemaFormRender.renderFieldRow(
30
+ {
31
+ key: `${field.key}[${i}]`,
32
+ prop: itemSchema,
33
+ required: false,
34
+ value: item,
35
+ onChange: (next) => field.onChange(jsonSchemaFormRender.setIndex(items, i, next))
36
+ },
37
+ childCtx,
38
+ { labelOverride: `Item ${i + 1}` }
39
+ ) }),
40
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
41
+ ItemControls,
42
+ {
43
+ onUp: i > 0 ? () => field.onChange(jsonSchemaFormRender.moveItem(items, i, i - 1)) : void 0,
44
+ onDown: i < items.length - 1 ? () => field.onChange(jsonSchemaFormRender.moveItem(items, i, i + 1)) : void 0,
45
+ onRemove: () => field.onChange(jsonSchemaFormRender.removeIndex(items, i)),
46
+ index: i
47
+ }
48
+ )
49
+ ] }, i)),
50
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
51
+ button.Button,
52
+ {
53
+ type: "button",
54
+ variant: "outline",
55
+ size: "sm",
56
+ className: "gap-1.5",
57
+ onClick: () => field.onChange([...items, jsonSchemaFormRender.seedFromSchema(itemSchema)]),
58
+ children: [
59
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiAdd.UiAdd, className: "text-sm" }),
60
+ "Add item"
61
+ ]
62
+ }
63
+ )
64
+ ] });
65
+ }
66
+ function ItemControls({
67
+ onUp,
68
+ onDown,
69
+ onRemove,
70
+ index
71
+ }) {
72
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
73
+ /* @__PURE__ */ jsxRuntime.jsx(
74
+ "button",
75
+ {
76
+ type: "button",
77
+ "aria-label": `Move item ${index + 1} up`,
78
+ disabled: !onUp,
79
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30",
80
+ onClick: onUp,
81
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiChevronUp.UiChevronUp, className: "text-sm" })
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsxRuntime.jsx(
85
+ "button",
86
+ {
87
+ type: "button",
88
+ "aria-label": `Move item ${index + 1} down`,
89
+ disabled: !onDown,
90
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30",
91
+ onClick: onDown,
92
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiChevronDown.UiChevronDown, className: "text-sm" })
93
+ }
94
+ ),
95
+ /* @__PURE__ */ jsxRuntime.jsx(
96
+ "button",
97
+ {
98
+ type: "button",
99
+ "aria-label": `Remove item ${index + 1}`,
100
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
101
+ onClick: onRemove,
102
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiTrash.UiTrash, className: "text-sm" })
103
+ }
104
+ )
105
+ ] });
106
+ }
107
+ function TagArray({
108
+ field,
109
+ fieldId,
110
+ readOnly
111
+ }) {
112
+ const tags = toStringArray(field.value);
113
+ function commit(raw, input) {
114
+ const next = raw.split(",").map((p) => p.trim()).filter(Boolean);
115
+ if (next.length === 0) return;
116
+ field.onChange([...tags, ...next]);
117
+ input.value = "";
118
+ }
119
+ function handleKeyDown(e) {
120
+ const input = e.currentTarget;
121
+ if (e.key === "Enter" || e.key === ",") {
122
+ e.preventDefault();
123
+ commit(input.value, input);
124
+ return;
125
+ }
126
+ if (e.key === "Backspace" && input.value === "" && tags.length > 0) {
127
+ field.onChange(tags.slice(0, -1));
128
+ }
129
+ }
130
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1 shadow-sm", children: [
131
+ tags.map((tag, i) => /* @__PURE__ */ jsxRuntime.jsxs(
132
+ "span",
133
+ {
134
+ className: "inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs",
135
+ children: [
136
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: tag }),
137
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
138
+ "button",
139
+ {
140
+ type: "button",
141
+ className: "text-muted-foreground hover:text-foreground",
142
+ "aria-label": `Remove ${tag}`,
143
+ onClick: () => field.onChange(tags.filter((_, idx) => idx !== i)),
144
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClose.UiClose })
145
+ }
146
+ )
147
+ ]
148
+ },
149
+ `${tag}-${i}`
150
+ )),
151
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
152
+ "input",
153
+ {
154
+ id: fieldId,
155
+ "data-jsf-input": true,
156
+ className: "min-w-32 flex-1 bg-transparent px-1 py-1 text-sm outline-none",
157
+ placeholder: tags.length === 0 ? jsonSchemaFormFields.defaultPlaceholder(field.schema) : "",
158
+ onKeyDown: handleKeyDown,
159
+ onBlur: (e) => commit(e.currentTarget.value, e.currentTarget)
160
+ }
161
+ )
162
+ ] });
163
+ }
164
+ function toStringArray(value) {
165
+ if (Array.isArray(value)) return value.map(String);
166
+ return [];
167
+ }
168
+ exports.ArrayControl = ArrayControl;
169
+ //# sourceMappingURL=json-schema-form-array.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-array.cjs","sources":["../../src/components/json-schema-form-array.tsx"],"sourcesContent":["import { type KeyboardEvent } from \"react\";\nimport { Icon } from \"../data/Icon\";\nimport { UiAdd, UiChevronDown, UiChevronUp, UiClose, UiTrash } from \"../icons\";\nimport { Button } from \"./button\";\nimport { defaultPlaceholder } from \"./json-schema-form-fields\";\nimport { isScalarStringItems } from \"./json-schema-form-resolve\";\nimport {\n moveItem,\n removeIndex,\n renderFieldRow,\n seedFromSchema,\n setIndex,\n type RenderContext,\n} from \"./json-schema-form-render\";\nimport type { FieldControl } from \"./json-schema-form-types\";\n\n// ArrayControl is a hybrid: plain string-item arrays keep the compact tag UI;\n// anything richer (objects, numbers, enums, nested arrays) renders one recursive\n// control per item with add / remove / reorder.\nexport function ArrayControl({\n field,\n fieldId,\n ctx,\n}: {\n field: FieldControl;\n fieldId: string;\n ctx: RenderContext;\n}) {\n // A read-only array marks its whole subtree non-editable: no add/remove/reorder\n // and item inputs disabled (a child the schema marks readOnly still renders as\n // a value span).\n const readOnly = ctx.readOnly || field.readOnly === true;\n if (isScalarStringItems(field.itemSchema)) {\n return <TagArray field={field} fieldId={fieldId} readOnly={readOnly} />;\n }\n const items = Array.isArray(field.value) ? field.value : [];\n const itemSchema = field.itemSchema ?? { type: \"string\" };\n const childCtx: RenderContext = { ...ctx, readOnly, depth: ctx.depth + 1 };\n\n return (\n <div className=\"space-y-2 rounded-md border border-input p-2\">\n {items.map((item, i) => (\n <div key={i} className=\"grid grid-cols-[1fr_auto] items-start gap-2\">\n <div className=\"min-w-0\">\n {renderFieldRow(\n {\n key: `${field.key}[${i}]`,\n prop: itemSchema,\n required: false,\n value: item,\n onChange: (next) => field.onChange(setIndex(items, i, next)),\n },\n childCtx,\n { labelOverride: `Item ${i + 1}` },\n )}\n </div>\n {!readOnly && (\n <ItemControls\n onUp={i > 0 ? () => field.onChange(moveItem(items, i, i - 1)) : undefined}\n onDown={i < items.length - 1 ? () => field.onChange(moveItem(items, i, i + 1)) : undefined}\n onRemove={() => field.onChange(removeIndex(items, i))}\n index={i}\n />\n )}\n </div>\n ))}\n {!readOnly && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"gap-1.5\"\n onClick={() => field.onChange([...items, seedFromSchema(itemSchema)])}\n >\n <Icon icon={UiAdd} className=\"text-sm\" />\n Add item\n </Button>\n )}\n </div>\n );\n}\n\nfunction ItemControls({\n onUp,\n onDown,\n onRemove,\n index,\n}: {\n onUp: (() => void) | undefined;\n onDown: (() => void) | undefined;\n onRemove: () => void;\n index: number;\n}) {\n return (\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n aria-label={`Move item ${index + 1} up`}\n disabled={!onUp}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30\"\n onClick={onUp}\n >\n <Icon icon={UiChevronUp} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n aria-label={`Move item ${index + 1} down`}\n disabled={!onDown}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30\"\n onClick={onDown}\n >\n <Icon icon={UiChevronDown} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n aria-label={`Remove item ${index + 1}`}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground\"\n onClick={onRemove}\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\n// TagArray is the compact tag editor for plain string-item arrays.\nfunction TagArray({\n field,\n fieldId,\n readOnly,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n}) {\n const tags = toStringArray(field.value);\n\n function commit(raw: string, input: HTMLInputElement) {\n const next = raw\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean);\n if (next.length === 0) return;\n field.onChange([...tags, ...next]);\n input.value = \"\";\n }\n\n function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n const input = e.currentTarget;\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n commit(input.value, input);\n return;\n }\n if (e.key === \"Backspace\" && input.value === \"\" && tags.length > 0) {\n field.onChange(tags.slice(0, -1));\n }\n }\n\n return (\n <div className=\"flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1 shadow-sm\">\n {tags.map((tag, i) => (\n <span\n key={`${tag}-${i}`}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <span className=\"truncate\">{tag}</span>\n {!readOnly && (\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground\"\n aria-label={`Remove ${tag}`}\n onClick={() => field.onChange(tags.filter((_, idx) => idx !== i))}\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </span>\n ))}\n {!readOnly && (\n <input\n id={fieldId}\n data-jsf-input\n className=\"min-w-32 flex-1 bg-transparent px-1 py-1 text-sm outline-none\"\n placeholder={tags.length === 0 ? defaultPlaceholder(field.schema) : \"\"}\n onKeyDown={handleKeyDown}\n onBlur={(e) => commit(e.currentTarget.value, e.currentTarget)}\n />\n )}\n </div>\n );\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String);\n return [];\n}\n"],"names":["isScalarStringItems","jsx","jsxs","renderFieldRow","setIndex","moveItem","removeIndex","Button","seedFromSchema","Icon","UiAdd","UiChevronUp","UiChevronDown","UiTrash","UiClose","defaultPlaceholder"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { RenderContext } from './json-schema-form-render';
2
+ import { FieldControl } from './json-schema-form-types';
3
+ export declare function ArrayControl({ field, fieldId, ctx, }: {
4
+ field: FieldControl;
5
+ fieldId: string;
6
+ ctx: RenderContext;
7
+ }): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=json-schema-form-array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-array.d.ts","sourceRoot":"","sources":["../../src/components/json-schema-form-array.tsx"],"names":[],"mappings":"AAMA,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAK7D,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,aAAa,CAAC;CACpB,2CAqDA"}
@@ -0,0 +1,169 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "react";
3
+ import { Icon } from "../data/Icon.js";
4
+ import { Button } from "./button.js";
5
+ import { defaultPlaceholder } from "./json-schema-form-fields.js";
6
+ import { isScalarStringItems } from "./json-schema-form-resolve.js";
7
+ import { renderFieldRow, setIndex, removeIndex, moveItem, seedFromSchema } from "./json-schema-form-render.js";
8
+ import { UiAdd } from "../icons/components/UiAdd.js";
9
+ import { UiClose } from "../icons/components/UiClose.js";
10
+ import { UiChevronUp } from "../icons/components/UiChevronUp.js";
11
+ import { UiChevronDown } from "../icons/components/UiChevronDown.js";
12
+ import { UiTrash } from "../icons/components/UiTrash.js";
13
+ function ArrayControl({
14
+ field,
15
+ fieldId,
16
+ ctx
17
+ }) {
18
+ const readOnly = ctx.readOnly || field.readOnly === true;
19
+ if (isScalarStringItems(field.itemSchema)) {
20
+ return /* @__PURE__ */ jsx(TagArray, { field, fieldId, readOnly });
21
+ }
22
+ const items = Array.isArray(field.value) ? field.value : [];
23
+ const itemSchema = field.itemSchema ?? { type: "string" };
24
+ const childCtx = { ...ctx, readOnly, depth: ctx.depth + 1 };
25
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border border-input p-2", children: [
26
+ items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_auto] items-start gap-2", children: [
27
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: renderFieldRow(
28
+ {
29
+ key: `${field.key}[${i}]`,
30
+ prop: itemSchema,
31
+ required: false,
32
+ value: item,
33
+ onChange: (next) => field.onChange(setIndex(items, i, next))
34
+ },
35
+ childCtx,
36
+ { labelOverride: `Item ${i + 1}` }
37
+ ) }),
38
+ !readOnly && /* @__PURE__ */ jsx(
39
+ ItemControls,
40
+ {
41
+ onUp: i > 0 ? () => field.onChange(moveItem(items, i, i - 1)) : void 0,
42
+ onDown: i < items.length - 1 ? () => field.onChange(moveItem(items, i, i + 1)) : void 0,
43
+ onRemove: () => field.onChange(removeIndex(items, i)),
44
+ index: i
45
+ }
46
+ )
47
+ ] }, i)),
48
+ !readOnly && /* @__PURE__ */ jsxs(
49
+ Button,
50
+ {
51
+ type: "button",
52
+ variant: "outline",
53
+ size: "sm",
54
+ className: "gap-1.5",
55
+ onClick: () => field.onChange([...items, seedFromSchema(itemSchema)]),
56
+ children: [
57
+ /* @__PURE__ */ jsx(Icon, { icon: UiAdd, className: "text-sm" }),
58
+ "Add item"
59
+ ]
60
+ }
61
+ )
62
+ ] });
63
+ }
64
+ function ItemControls({
65
+ onUp,
66
+ onDown,
67
+ onRemove,
68
+ index
69
+ }) {
70
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
71
+ /* @__PURE__ */ jsx(
72
+ "button",
73
+ {
74
+ type: "button",
75
+ "aria-label": `Move item ${index + 1} up`,
76
+ disabled: !onUp,
77
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30",
78
+ onClick: onUp,
79
+ children: /* @__PURE__ */ jsx(Icon, { icon: UiChevronUp, className: "text-sm" })
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsx(
83
+ "button",
84
+ {
85
+ type: "button",
86
+ "aria-label": `Move item ${index + 1} down`,
87
+ disabled: !onDown,
88
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30",
89
+ onClick: onDown,
90
+ children: /* @__PURE__ */ jsx(Icon, { icon: UiChevronDown, className: "text-sm" })
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsx(
94
+ "button",
95
+ {
96
+ type: "button",
97
+ "aria-label": `Remove item ${index + 1}`,
98
+ className: "inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
99
+ onClick: onRemove,
100
+ children: /* @__PURE__ */ jsx(Icon, { icon: UiTrash, className: "text-sm" })
101
+ }
102
+ )
103
+ ] });
104
+ }
105
+ function TagArray({
106
+ field,
107
+ fieldId,
108
+ readOnly
109
+ }) {
110
+ const tags = toStringArray(field.value);
111
+ function commit(raw, input) {
112
+ const next = raw.split(",").map((p) => p.trim()).filter(Boolean);
113
+ if (next.length === 0) return;
114
+ field.onChange([...tags, ...next]);
115
+ input.value = "";
116
+ }
117
+ function handleKeyDown(e) {
118
+ const input = e.currentTarget;
119
+ if (e.key === "Enter" || e.key === ",") {
120
+ e.preventDefault();
121
+ commit(input.value, input);
122
+ return;
123
+ }
124
+ if (e.key === "Backspace" && input.value === "" && tags.length > 0) {
125
+ field.onChange(tags.slice(0, -1));
126
+ }
127
+ }
128
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1 shadow-sm", children: [
129
+ tags.map((tag, i) => /* @__PURE__ */ jsxs(
130
+ "span",
131
+ {
132
+ className: "inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs",
133
+ children: [
134
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: tag }),
135
+ !readOnly && /* @__PURE__ */ jsx(
136
+ "button",
137
+ {
138
+ type: "button",
139
+ className: "text-muted-foreground hover:text-foreground",
140
+ "aria-label": `Remove ${tag}`,
141
+ onClick: () => field.onChange(tags.filter((_, idx) => idx !== i)),
142
+ children: /* @__PURE__ */ jsx(Icon, { icon: UiClose })
143
+ }
144
+ )
145
+ ]
146
+ },
147
+ `${tag}-${i}`
148
+ )),
149
+ !readOnly && /* @__PURE__ */ jsx(
150
+ "input",
151
+ {
152
+ id: fieldId,
153
+ "data-jsf-input": true,
154
+ className: "min-w-32 flex-1 bg-transparent px-1 py-1 text-sm outline-none",
155
+ placeholder: tags.length === 0 ? defaultPlaceholder(field.schema) : "",
156
+ onKeyDown: handleKeyDown,
157
+ onBlur: (e) => commit(e.currentTarget.value, e.currentTarget)
158
+ }
159
+ )
160
+ ] });
161
+ }
162
+ function toStringArray(value) {
163
+ if (Array.isArray(value)) return value.map(String);
164
+ return [];
165
+ }
166
+ export {
167
+ ArrayControl
168
+ };
169
+ //# sourceMappingURL=json-schema-form-array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-array.js","sources":["../../src/components/json-schema-form-array.tsx"],"sourcesContent":["import { type KeyboardEvent } from \"react\";\nimport { Icon } from \"../data/Icon\";\nimport { UiAdd, UiChevronDown, UiChevronUp, UiClose, UiTrash } from \"../icons\";\nimport { Button } from \"./button\";\nimport { defaultPlaceholder } from \"./json-schema-form-fields\";\nimport { isScalarStringItems } from \"./json-schema-form-resolve\";\nimport {\n moveItem,\n removeIndex,\n renderFieldRow,\n seedFromSchema,\n setIndex,\n type RenderContext,\n} from \"./json-schema-form-render\";\nimport type { FieldControl } from \"./json-schema-form-types\";\n\n// ArrayControl is a hybrid: plain string-item arrays keep the compact tag UI;\n// anything richer (objects, numbers, enums, nested arrays) renders one recursive\n// control per item with add / remove / reorder.\nexport function ArrayControl({\n field,\n fieldId,\n ctx,\n}: {\n field: FieldControl;\n fieldId: string;\n ctx: RenderContext;\n}) {\n // A read-only array marks its whole subtree non-editable: no add/remove/reorder\n // and item inputs disabled (a child the schema marks readOnly still renders as\n // a value span).\n const readOnly = ctx.readOnly || field.readOnly === true;\n if (isScalarStringItems(field.itemSchema)) {\n return <TagArray field={field} fieldId={fieldId} readOnly={readOnly} />;\n }\n const items = Array.isArray(field.value) ? field.value : [];\n const itemSchema = field.itemSchema ?? { type: \"string\" };\n const childCtx: RenderContext = { ...ctx, readOnly, depth: ctx.depth + 1 };\n\n return (\n <div className=\"space-y-2 rounded-md border border-input p-2\">\n {items.map((item, i) => (\n <div key={i} className=\"grid grid-cols-[1fr_auto] items-start gap-2\">\n <div className=\"min-w-0\">\n {renderFieldRow(\n {\n key: `${field.key}[${i}]`,\n prop: itemSchema,\n required: false,\n value: item,\n onChange: (next) => field.onChange(setIndex(items, i, next)),\n },\n childCtx,\n { labelOverride: `Item ${i + 1}` },\n )}\n </div>\n {!readOnly && (\n <ItemControls\n onUp={i > 0 ? () => field.onChange(moveItem(items, i, i - 1)) : undefined}\n onDown={i < items.length - 1 ? () => field.onChange(moveItem(items, i, i + 1)) : undefined}\n onRemove={() => field.onChange(removeIndex(items, i))}\n index={i}\n />\n )}\n </div>\n ))}\n {!readOnly && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"gap-1.5\"\n onClick={() => field.onChange([...items, seedFromSchema(itemSchema)])}\n >\n <Icon icon={UiAdd} className=\"text-sm\" />\n Add item\n </Button>\n )}\n </div>\n );\n}\n\nfunction ItemControls({\n onUp,\n onDown,\n onRemove,\n index,\n}: {\n onUp: (() => void) | undefined;\n onDown: (() => void) | undefined;\n onRemove: () => void;\n index: number;\n}) {\n return (\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n aria-label={`Move item ${index + 1} up`}\n disabled={!onUp}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30\"\n onClick={onUp}\n >\n <Icon icon={UiChevronUp} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n aria-label={`Move item ${index + 1} down`}\n disabled={!onDown}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30\"\n onClick={onDown}\n >\n <Icon icon={UiChevronDown} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n aria-label={`Remove item ${index + 1}`}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground\"\n onClick={onRemove}\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\n// TagArray is the compact tag editor for plain string-item arrays.\nfunction TagArray({\n field,\n fieldId,\n readOnly,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n}) {\n const tags = toStringArray(field.value);\n\n function commit(raw: string, input: HTMLInputElement) {\n const next = raw\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean);\n if (next.length === 0) return;\n field.onChange([...tags, ...next]);\n input.value = \"\";\n }\n\n function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n const input = e.currentTarget;\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n commit(input.value, input);\n return;\n }\n if (e.key === \"Backspace\" && input.value === \"\" && tags.length > 0) {\n field.onChange(tags.slice(0, -1));\n }\n }\n\n return (\n <div className=\"flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1 shadow-sm\">\n {tags.map((tag, i) => (\n <span\n key={`${tag}-${i}`}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <span className=\"truncate\">{tag}</span>\n {!readOnly && (\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground\"\n aria-label={`Remove ${tag}`}\n onClick={() => field.onChange(tags.filter((_, idx) => idx !== i))}\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </span>\n ))}\n {!readOnly && (\n <input\n id={fieldId}\n data-jsf-input\n className=\"min-w-32 flex-1 bg-transparent px-1 py-1 text-sm outline-none\"\n placeholder={tags.length === 0 ? defaultPlaceholder(field.schema) : \"\"}\n onKeyDown={handleKeyDown}\n onBlur={(e) => commit(e.currentTarget.value, e.currentTarget)}\n />\n )}\n </div>\n );\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String);\n return [];\n}\n"],"names":[],"mappings":"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"}