@sealcode/jdd-editor 0.1.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 (192) hide show
  1. package/.arcconfig +12 -0
  2. package/.arclint +18 -0
  3. package/.eslintrc.js +37 -0
  4. package/.mocharc.js +6 -0
  5. package/.nycrc +6 -0
  6. package/.prettierrc +14 -0
  7. package/@types/component-preview-actions.d.ts +43 -0
  8. package/@types/components.sreact.d.ts +48 -0
  9. package/@types/controllers/autogrow-textarea.stimulus.d.ts +5 -0
  10. package/@types/controllers/component-debugger.stimulus.d.ts +28 -0
  11. package/@types/controllers/exportable-textarea.stimulus.d.ts +7 -0
  12. package/@types/controllers/input-image-preview.stimulus.d.ts +5 -0
  13. package/@types/controllers/jdd-table-paste.stimulus.d.ts +8 -0
  14. package/@types/controllers/json-editor.stimulus.d.ts +9 -0
  15. package/@types/controllers/markdown-textarea.stimulus.d.ts +20 -0
  16. package/@types/controllers/refresh-on-ts-changes.stimulus.d.ts +6 -0
  17. package/@types/controllers/refresh-styles.stimulus.d.ts +6 -0
  18. package/@types/controllers/submit-on-input.stimulus.d.ts +7 -0
  19. package/@types/controllers/toast.stimulus.d.ts +4 -0
  20. package/@types/edit-jdd-field.d.ts +22 -0
  21. package/@types/index.d.ts +2 -0
  22. package/@types/inputs/component-input-enum.d.ts +8 -0
  23. package/@types/inputs/component-input-image.d.ts +15 -0
  24. package/@types/inputs/component-input-list.d.ts +15 -0
  25. package/@types/inputs/component-input-single-reference.d.ts +11 -0
  26. package/@types/inputs/component-input-structured.d.ts +15 -0
  27. package/@types/inputs/component-input-table.d.ts +15 -0
  28. package/@types/inputs/component-input.d.ts +16 -0
  29. package/@types/inputs/print-arg-path.d.ts +1 -0
  30. package/@types/jdd-creator.d.ts +49 -0
  31. package/@types/jdd-page.d.ts +85 -0
  32. package/assets/icons/table-add-column-right.svg +1 -0
  33. package/assets/icons/table-add-row-below.svg +1 -0
  34. package/assets/icons/table-add-row-header-below.svg +1 -0
  35. package/assets/icons/table-delete-column.svg +1 -0
  36. package/assets/icons/table-delete-row.svg +1 -0
  37. package/assets/icons/table-move-column-right.svg +1 -0
  38. package/assets/icons/table-move-row-down.svg +1 -0
  39. package/assets/icons/table-move-row-up.svg +1 -0
  40. package/assets/styles/component-admin-table.jdd-page.css +11 -0
  41. package/assets/styles/component-debugger.jdd-page.css +71 -0
  42. package/assets/styles/components.jdd-page.css +286 -0
  43. package/assets/styles/grow-wrap.css +33 -0
  44. package/assets/styles/markdown-editor.css +42 -0
  45. package/dist/src/autogrow-textarea.stimulus.js +13 -0
  46. package/dist/src/autogrow-textarea.stimulus.js.map +7 -0
  47. package/dist/src/component-debugger.stimulus.js +190 -0
  48. package/dist/src/component-debugger.stimulus.js.map +7 -0
  49. package/dist/src/component-preview-actions.js +439 -0
  50. package/dist/src/component-preview-actions.js.map +7 -0
  51. package/dist/src/components.sreact.js +93 -0
  52. package/dist/src/components.sreact.js.map +7 -0
  53. package/dist/src/controllers/autogrow-textarea.stimulus.js +13 -0
  54. package/dist/src/controllers/autogrow-textarea.stimulus.js.map +7 -0
  55. package/dist/src/controllers/component-debugger.stimulus.js +193 -0
  56. package/dist/src/controllers/component-debugger.stimulus.js.map +7 -0
  57. package/dist/src/controllers/exportable-textarea.stimulus.js +71 -0
  58. package/dist/src/controllers/exportable-textarea.stimulus.js.map +7 -0
  59. package/dist/src/controllers/input-image-preview.stimulus.js +30 -0
  60. package/dist/src/controllers/input-image-preview.stimulus.js.map +7 -0
  61. package/dist/src/controllers/jdd-table-paste.stimulus.js +78 -0
  62. package/dist/src/controllers/jdd-table-paste.stimulus.js.map +7 -0
  63. package/dist/src/controllers/json-editor.stimulus.js +114 -0
  64. package/dist/src/controllers/json-editor.stimulus.js.map +7 -0
  65. package/dist/src/controllers/markdown-textarea.stimulus.js +174 -0
  66. package/dist/src/controllers/markdown-textarea.stimulus.js.map +7 -0
  67. package/dist/src/controllers/refresh-on-ts-changes.stimulus.js +90 -0
  68. package/dist/src/controllers/refresh-on-ts-changes.stimulus.js.map +7 -0
  69. package/dist/src/controllers/refresh-styles.stimulus.js +67 -0
  70. package/dist/src/controllers/refresh-styles.stimulus.js.map +7 -0
  71. package/dist/src/controllers/submit-on-input.stimulus.js +55 -0
  72. package/dist/src/controllers/submit-on-input.stimulus.js.map +7 -0
  73. package/dist/src/controllers/toast.stimulus.js +19 -0
  74. package/dist/src/controllers/toast.stimulus.js.map +7 -0
  75. package/dist/src/edit-jdd-field.js +94 -0
  76. package/dist/src/edit-jdd-field.js.map +7 -0
  77. package/dist/src/exportable-textarea.stimulus.js +71 -0
  78. package/dist/src/exportable-textarea.stimulus.js.map +7 -0
  79. package/dist/src/index.js +3 -0
  80. package/dist/src/index.js.map +7 -0
  81. package/dist/src/input-image-preview.stimulus.js +30 -0
  82. package/dist/src/input-image-preview.stimulus.js.map +7 -0
  83. package/dist/src/inputs/component-input-enum.js +30 -0
  84. package/dist/src/inputs/component-input-enum.js.map +7 -0
  85. package/dist/src/inputs/component-input-image.js +58 -0
  86. package/dist/src/inputs/component-input-image.js.map +7 -0
  87. package/dist/src/inputs/component-input-list.js +74 -0
  88. package/dist/src/inputs/component-input-list.js.map +7 -0
  89. package/dist/src/inputs/component-input-single-reference.js +31 -0
  90. package/dist/src/inputs/component-input-single-reference.js.map +7 -0
  91. package/dist/src/inputs/component-input-structured.js +36 -0
  92. package/dist/src/inputs/component-input-structured.js.map +7 -0
  93. package/dist/src/inputs/component-input-table.js +228 -0
  94. package/dist/src/inputs/component-input-table.js.map +7 -0
  95. package/dist/src/inputs/component-input.js +129 -0
  96. package/dist/src/inputs/component-input.js.map +7 -0
  97. package/dist/src/inputs/print-arg-path.js +7 -0
  98. package/dist/src/inputs/print-arg-path.js.map +7 -0
  99. package/dist/src/jdd-creator.js +131 -0
  100. package/dist/src/jdd-creator.js.map +7 -0
  101. package/dist/src/jdd-page.js +339 -0
  102. package/dist/src/jdd-page.js.map +7 -0
  103. package/dist/src/jdd-table-paste.stimulus.js +78 -0
  104. package/dist/src/jdd-table-paste.stimulus.js.map +7 -0
  105. package/dist/src/json-editor.stimulus.js +114 -0
  106. package/dist/src/json-editor.stimulus.js.map +7 -0
  107. package/dist/src/markdown-textarea.stimulus.js +174 -0
  108. package/dist/src/markdown-textarea.stimulus.js.map +7 -0
  109. package/dist/src/submit-on-input.stimulus.js +55 -0
  110. package/dist/src/submit-on-input.stimulus.js.map +7 -0
  111. package/dist/src/toast.stimulus.js +19 -0
  112. package/dist/src/toast.stimulus.js.map +7 -0
  113. package/esbuild.cjs +20 -0
  114. package/esbuild.js +23 -0
  115. package/jenkins.sanity.sh +3 -0
  116. package/lib/component-preview-actions.js +286 -0
  117. package/lib/component-preview-actions.js.map +1 -0
  118. package/lib/components.sreact.js +102 -0
  119. package/lib/components.sreact.js.map +1 -0
  120. package/lib/controllers/autogrow-textarea.stimulus.js +15 -0
  121. package/lib/controllers/autogrow-textarea.stimulus.js.map +1 -0
  122. package/lib/controllers/component-debugger.stimulus.js +188 -0
  123. package/lib/controllers/component-debugger.stimulus.js.map +1 -0
  124. package/lib/controllers/exportable-textarea.stimulus.js +79 -0
  125. package/lib/controllers/exportable-textarea.stimulus.js.map +1 -0
  126. package/lib/controllers/input-image-preview.stimulus.js +28 -0
  127. package/lib/controllers/input-image-preview.stimulus.js.map +1 -0
  128. package/lib/controllers/jdd-table-paste.stimulus.js +84 -0
  129. package/lib/controllers/jdd-table-paste.stimulus.js.map +1 -0
  130. package/lib/controllers/json-editor.stimulus.js +134 -0
  131. package/lib/controllers/json-editor.stimulus.js.map +1 -0
  132. package/lib/controllers/markdown-textarea.stimulus.js +186 -0
  133. package/lib/controllers/markdown-textarea.stimulus.js.map +1 -0
  134. package/lib/controllers/refresh-on-ts-changes.stimulus.js +123 -0
  135. package/lib/controllers/refresh-on-ts-changes.stimulus.js.map +1 -0
  136. package/lib/controllers/refresh-styles.stimulus.js +66 -0
  137. package/lib/controllers/refresh-styles.stimulus.js.map +1 -0
  138. package/lib/controllers/submit-on-input.stimulus.js +48 -0
  139. package/lib/controllers/submit-on-input.stimulus.js.map +1 -0
  140. package/lib/controllers/toast.stimulus.js +16 -0
  141. package/lib/controllers/toast.stimulus.js.map +1 -0
  142. package/lib/edit-jdd-field.js +102 -0
  143. package/lib/edit-jdd-field.js.map +1 -0
  144. package/lib/index.js +19 -0
  145. package/lib/index.js.map +1 -0
  146. package/lib/inputs/component-input-enum.js +25 -0
  147. package/lib/inputs/component-input-enum.js.map +1 -0
  148. package/lib/inputs/component-input-image.js +47 -0
  149. package/lib/inputs/component-input-image.js.map +1 -0
  150. package/lib/inputs/component-input-list.js +61 -0
  151. package/lib/inputs/component-input-list.js.map +1 -0
  152. package/lib/inputs/component-input-single-reference.js +36 -0
  153. package/lib/inputs/component-input-single-reference.js.map +1 -0
  154. package/lib/inputs/component-input-structured.js +42 -0
  155. package/lib/inputs/component-input-structured.js.map +1 -0
  156. package/lib/inputs/component-input-table.js +184 -0
  157. package/lib/inputs/component-input-table.js.map +1 -0
  158. package/lib/inputs/component-input.js +133 -0
  159. package/lib/inputs/component-input.js.map +1 -0
  160. package/lib/inputs/print-arg-path.js +7 -0
  161. package/lib/inputs/print-arg-path.js.map +1 -0
  162. package/lib/jdd-creator.js +113 -0
  163. package/lib/jdd-creator.js.map +1 -0
  164. package/lib/jdd-page.js +310 -0
  165. package/lib/jdd-page.js.map +1 -0
  166. package/package.json +61 -0
  167. package/src/component-preview-actions.ts +520 -0
  168. package/src/components.sreact.ts +100 -0
  169. package/src/controllers/autogrow-textarea.stimulus.ts +13 -0
  170. package/src/controllers/component-debugger.stimulus.ts +247 -0
  171. package/src/controllers/exportable-textarea.stimulus.ts +77 -0
  172. package/src/controllers/input-image-preview.stimulus.ts +29 -0
  173. package/src/controllers/jdd-table-paste.stimulus.ts +89 -0
  174. package/src/controllers/json-editor.stimulus.ts +127 -0
  175. package/src/controllers/markdown-textarea.stimulus.ts +198 -0
  176. package/src/controllers/refresh-on-ts-changes.stimulus.ts +112 -0
  177. package/src/controllers/refresh-styles.stimulus.ts +70 -0
  178. package/src/controllers/submit-on-input.stimulus.ts +66 -0
  179. package/src/controllers/toast.stimulus.ts +15 -0
  180. package/src/edit-jdd-field.ts +127 -0
  181. package/src/index.ts +2 -0
  182. package/src/inputs/component-input-enum.ts +36 -0
  183. package/src/inputs/component-input-image.ts +70 -0
  184. package/src/inputs/component-input-list.ts +91 -0
  185. package/src/inputs/component-input-single-reference.ts +45 -0
  186. package/src/inputs/component-input-structured.ts +51 -0
  187. package/src/inputs/component-input-table.ts +262 -0
  188. package/src/inputs/component-input.ts +158 -0
  189. package/src/inputs/print-arg-path.ts +3 -0
  190. package/src/jdd-creator.ts +151 -0
  191. package/src/jdd-page.ts +439 -0
  192. package/tsconfig.json +24 -0
@@ -0,0 +1,91 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import type { Context } from "koa";
3
+ import type { ComponentArgument, JDDContext, List } from "@sealcode/jdd";
4
+ import type { JDDPageState } from "../jdd-page.js";
5
+ import type { StatefulPage } from "@sealcode/sealgen";
6
+ import { ComponentInput } from "./component-input.js";
7
+ import type { ComponentPreviewActions } from "../component-preview-actions.js";
8
+ import { tempstream } from "tempstream";
9
+
10
+ export async function ComponentInputList<
11
+ State extends JDDPageState,
12
+ T extends ComponentArgument<unknown>
13
+ >({
14
+ state,
15
+ ctx,
16
+ arg_path,
17
+ arg,
18
+ value,
19
+ page,
20
+ makeJDDContext,
21
+ ...rest
22
+ }: {
23
+ state: State;
24
+ ctx: Context;
25
+ arg_path: string[];
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ arg: List<T, any>;
28
+ value: T[];
29
+ page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
30
+ makeJDDContext: (ctx: Context) => JDDContext;
31
+ makeAssetURL: (asset: string) => string;
32
+ }): Promise<string> {
33
+ if (!value) {
34
+ value = [];
35
+ }
36
+ return tempstream/* HTML */ `<fieldset
37
+ id="${`component-input-list-${arg_path.join("-")}`}"
38
+ >
39
+ <legend>${arg_path.at(-1)!}</legend>
40
+ ${value.map(
41
+ (value, i, all_values) =>
42
+ tempstream`<div style="display: flex">
43
+ ${ComponentInput({
44
+ ...rest,
45
+ ctx,
46
+ state,
47
+ arg_path: [...arg_path, i.toString()],
48
+ arg: arg.item_type,
49
+ value,
50
+ page,
51
+ makeJDDContext,
52
+ })}
53
+ ${page.makeActionButton(
54
+ state,
55
+ {
56
+ action: "move_array_item_down",
57
+ label: "↓",
58
+ disabled: i == all_values.length - 1,
59
+ },
60
+ arg_path,
61
+ i
62
+ )}
63
+ ${page.makeActionButton(
64
+ state,
65
+ {
66
+ action: "move_array_item_up",
67
+ label: "↑",
68
+ disabled: i == 0,
69
+ },
70
+ arg_path,
71
+ i
72
+ )}
73
+
74
+ ${page.makeActionButton(
75
+ state,
76
+ { action: "remove_array_item", label: "❌" },
77
+ arg_path,
78
+ i
79
+ )}
80
+ </div>`
81
+ )}
82
+ ${page.makeActionButton(
83
+ state,
84
+ {
85
+ action: "add_array_item",
86
+ label: "➕",
87
+ },
88
+ arg_path
89
+ )}
90
+ </fieldset>`;
91
+ }
@@ -0,0 +1,45 @@
1
+ import type { Context } from "koa";
2
+ import type { JDDContext, SingleReference } from "@sealcode/jdd";
3
+ import { printArgPath } from "./print-arg-path.js";
4
+
5
+ export async function ComponentInputSingleReference<
6
+ State,
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ T extends SingleReference<any>
9
+ >({
10
+ ctx,
11
+ arg_path,
12
+ arg,
13
+ value,
14
+ onchange,
15
+ makeJDDContext,
16
+ }: {
17
+ ctx: Context;
18
+ state: State;
19
+ arg_path: string[];
20
+ arg: T;
21
+ value: string;
22
+ onchange?: string;
23
+ makeJDDContext: (ctx: Context) => JDDContext;
24
+ }): Promise<string> {
25
+ const values = await arg.getValues(makeJDDContext(ctx));
26
+ const ret = `<div>
27
+ <label>
28
+ ${arg_path.at(-1) || ""}
29
+ <select name="${`$${printArgPath(arg_path)}`}" onchange="${onchange}">
30
+ ${values
31
+ .sort((v1, v2) => (v1.label > v2.label ? 1 : -1))
32
+ .map(
33
+ (v) => /* HTML */ `<option
34
+ value="${v.value}"
35
+ ${value == v.value ? "selected" : ""}
36
+ >
37
+ ${v.label}
38
+ </option>`
39
+ )
40
+ .join("")}
41
+ </select>
42
+ </label>
43
+ </div>`;
44
+ return ret;
45
+ }
@@ -0,0 +1,51 @@
1
+ import type { Context } from "koa";
2
+ import type { ComponentArgument, JDDContext, Structured } from "@sealcode/jdd";
3
+ import type { StatefulPage } from "@sealcode/sealgen";
4
+ import { ComponentInput } from "./component-input.js";
5
+ import type { JDDPageState } from "../jdd-page.js";
6
+ import type { ComponentPreviewActions } from "../component-preview-actions.js";
7
+
8
+ export async function ComponentInputStructured<
9
+ T extends Structured<Record<string, ComponentArgument<unknown>>>
10
+ >({
11
+ state,
12
+ ctx,
13
+ arg_path,
14
+ arg,
15
+ value,
16
+ page,
17
+ ...rest
18
+ }: {
19
+ state: JDDPageState;
20
+ ctx: Context;
21
+ arg_path: string[];
22
+ arg: T;
23
+ value: Record<string, unknown>;
24
+ page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
25
+ makeJDDContext: (ctx: Context) => JDDContext;
26
+ makeAssetURL: (asset: string) => string;
27
+ }) {
28
+ return /* HTML */ `<fieldset
29
+ id="${`component-input-structured-${arg_path.join("-")}`}"
30
+ >
31
+ <legend>{arg_path.at(-1)}</legend>
32
+ ${(
33
+ await Promise.all(
34
+ Object.entries(arg.structure).map(async ([arg_name, arg]) => {
35
+ const ret = `<div>
36
+ ${await ComponentInput({
37
+ ctx,
38
+ state,
39
+ arg_path: [...arg_path, arg_name],
40
+ arg,
41
+ value: value[arg_name],
42
+ page,
43
+ ...rest,
44
+ })}
45
+ </div>`;
46
+ return ret;
47
+ })
48
+ )
49
+ ).join("")}
50
+ </fieldset>`;
51
+ }
@@ -0,0 +1,262 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import type { JDDContext, Table, TableData } from "@sealcode/jdd";
3
+ import { Markdown } from "@sealcode/jdd";
4
+ import { isTableHeader } from "@sealcode/jdd";
5
+ import type { StatefulPage } from "@sealcode/sealgen";
6
+ import type { Context } from "koa";
7
+ import { tempstream } from "tempstream";
8
+ import { ComponentInput } from "./component-input.js";
9
+ import type { ComponentPreviewActions } from "../component-preview-actions.js";
10
+ import type { JDDPageState } from "../jdd-page.js";
11
+
12
+ export async function ComponentInputTable<
13
+ State extends JDDPageState,
14
+ CellType,
15
+ HeaderType
16
+ >({
17
+ state,
18
+ arg_path,
19
+ ctx,
20
+ arg,
21
+ value,
22
+ page,
23
+ makeJDDContext,
24
+ makeAssetURL,
25
+ }: {
26
+ state: State;
27
+ ctx: Context;
28
+ arg_path: string[];
29
+ arg: Table<CellType, HeaderType>;
30
+ value: TableData<CellType, HeaderType>;
31
+ page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
32
+ makeJDDContext: (ctx: Context) => JDDContext;
33
+ makeAssetURL: (asset: string) => string;
34
+ }): Promise<string> {
35
+ if (!value) {
36
+ value = await arg.getEmptyValue(makeJDDContext(ctx));
37
+ }
38
+
39
+ const show_paste =
40
+ arg.cell_type instanceof Markdown &&
41
+ arg.header_type instanceof Markdown;
42
+
43
+ return tempstream/* HTML */ `<fieldset>
44
+ <legend>${arg_path.at(-1)!}</legend>
45
+ <div>
46
+ ${show_paste
47
+ ? /* HTML */ `<input
48
+ type="button"
49
+ value="paste"
50
+ placeholder="paste table here"
51
+ data-jdd-table-paste-argpath-value="${arg_path.join(
52
+ "."
53
+ )}"
54
+ data-controller="jdd-table-paste"
55
+ />`
56
+ : ""}
57
+ <table
58
+ class="jdd-component-input--table"
59
+ style="position: relative; /* necessary for sticky th*/"
60
+ >
61
+ <tbody>
62
+ <tr>
63
+ <td></td>
64
+ ${[...Array(arg.getColumnsCount(value)).keys()]
65
+ .map(
66
+ (column_index) => /* HTML */ `<th
67
+ class="sticky sticky--top subdued"
68
+ >
69
+ ${page.makeActionButton(
70
+ state,
71
+ {
72
+ action: "remove_table_column",
73
+ label: "Remove column",
74
+ content: /* HTML */ `<img
75
+ width="20"
76
+ height="20"
77
+ src="${makeAssetURL(
78
+ "icons/table-delete-column.svg"
79
+ )}"
80
+ />`,
81
+ },
82
+ arg_path,
83
+ column_index
84
+ )}
85
+ ${column_index >=
86
+ arg.getColumnsCount(value) - 1
87
+ ? ""
88
+ : page.makeActionButton(
89
+ state,
90
+ {
91
+ action: "move_table_column_right",
92
+ label: "Move column to the right",
93
+ content: /* HTML */ `<img
94
+ width="20"
95
+ height="20"
96
+ src="${makeAssetURL(
97
+ "icons/table-move-column-right.svg"
98
+ )}"
99
+ />`,
100
+ },
101
+ arg_path,
102
+ column_index
103
+ )}
104
+ </th>`
105
+ )
106
+ .join("")}
107
+ </tr>
108
+ ${value.rows.map(
109
+ (row, row_index) => tempstream/* HTML */ `<tr>
110
+ <td class="sticky sticky--left subdued">
111
+ <div
112
+ style="display: flex; flex-flow: column; row-gap: 5px;"
113
+ >
114
+ ${page.makeActionButton(
115
+ state,
116
+ {
117
+ action: "remove_table_row",
118
+ label: "Remove row",
119
+ content: /* HTML */ `<img
120
+ width="20"
121
+ height="20"
122
+ src="${makeAssetURL(
123
+ "icons/table-delete-row.svg"
124
+ )}"
125
+ />`,
126
+ },
127
+ arg_path,
128
+ row_index
129
+ )}
130
+ ${page.makeActionButton(
131
+ state,
132
+ {
133
+ action: "move_table_row_down",
134
+ label: "Move this row down",
135
+ content: /* HTML */ `<img
136
+ width="20"
137
+ height="20"
138
+ src="${makeAssetURL(
139
+ "icons/table-move-row-down.svg"
140
+ )}"
141
+ />`,
142
+ },
143
+ arg_path,
144
+ row_index
145
+ )}
146
+ </div>
147
+ </td>
148
+ ${isTableHeader(row)
149
+ ? /* HTML */ tempstream`<th
150
+ colspan="${arg.getColumnsCount(value).toString()}"
151
+ >
152
+ ${ComponentInput({
153
+ state,
154
+ ctx,
155
+ arg_path: [
156
+ ...arg_path,
157
+ "rows",
158
+ row_index.toString(),
159
+ "header_content",
160
+ ],
161
+ arg: arg.header_type,
162
+ value: row.header_content,
163
+ page,
164
+ makeJDDContext,
165
+ makeAssetURL,
166
+ })}
167
+ </th>`
168
+ : row.cells.map(
169
+ (
170
+ cell,
171
+ cell_index
172
+ ) => tempstream/* HTML */ `<td>
173
+ ${ComponentInput({
174
+ ctx,
175
+ state,
176
+ arg_path: [
177
+ ...arg_path,
178
+ "rows",
179
+ row_index.toString(),
180
+ "cells",
181
+ cell_index.toString(),
182
+ ],
183
+ arg: arg.cell_type,
184
+ value: cell,
185
+ page,
186
+ makeJDDContext,
187
+ makeAssetURL,
188
+ })}
189
+ </td>`
190
+ )}
191
+ ${row_index == 0
192
+ ? /* HTML */ `<td
193
+ class="subdued"
194
+ rowspan="${value.rows.length.toString()}"
195
+ >
196
+ ${page.makeActionButton(
197
+ state,
198
+ {
199
+ action: "add_table_column",
200
+ label: "Add column",
201
+ content: /* HTML */ `<img
202
+ width="20"
203
+ height="20"
204
+ src="${makeAssetURL(
205
+ "icons/table-add-column-right.svg"
206
+ )}"
207
+ />`,
208
+ },
209
+ arg_path
210
+ )}
211
+ </td>`
212
+ : ""}
213
+ </tr>`
214
+ )}
215
+ <tr>
216
+ <td
217
+ class="subdued"
218
+ colspan="{(arg.getColumnsCount(value)"
219
+ +
220
+ 1).toString()}
221
+ >
222
+ ${page.makeActionButton(
223
+ state,
224
+ {
225
+ action: "add_table_row",
226
+ label: "Add table row",
227
+ content: /* HTML */ `<img
228
+ width="20"
229
+ height="20"
230
+ src="${makeAssetURL(
231
+ "icons/table-add-row-below.svg"
232
+ )}"
233
+ />`,
234
+ },
235
+ arg_path,
236
+ arg.getColumnsCount(value),
237
+ undefined
238
+ )}
239
+ ${page.makeActionButton(
240
+ state,
241
+ {
242
+ action: "add_table_row",
243
+ label: "Add table header",
244
+ content: /* HTML */ `<img
245
+ width="20"
246
+ height="20"
247
+ src="${makeAssetURL(
248
+ "icons/table-add-column-header-below.svg"
249
+ )}"
250
+ />`,
251
+ },
252
+ arg_path,
253
+ arg.getColumnsCount(value),
254
+ "header"
255
+ )}
256
+ </td>
257
+ </tr>
258
+ </tbody>
259
+ </table>
260
+ </div>
261
+ </fieldset>`;
262
+ }
@@ -0,0 +1,158 @@
1
+ import { printArgPath } from "./print-arg-path.js";
2
+ import type { Context } from "koa";
3
+ import type { ComponentArgument, JDDContext, TableData } from "@sealcode/jdd";
4
+ import { SingleReference } from "@sealcode/jdd";
5
+ import {
6
+ ComponentArguments,
7
+ Enum,
8
+ Image,
9
+ List,
10
+ Structured,
11
+ Table,
12
+ } from "@sealcode/jdd";
13
+ import { ComponentInputStructured } from "./component-input-structured.js";
14
+ import type { StatefulPage } from "@sealcode/sealgen";
15
+ import type { ComponentPreviewActions } from "../component-preview-actions.js";
16
+ import { ComponentInputList } from "./component-input-list.js";
17
+ import type { JDDPageState } from "../jdd-page.js";
18
+ import { ComponentInputEnum } from "./component-input-enum.js";
19
+ import { ComponentInputImage } from "./component-input-image.js";
20
+ import { ComponentInputTable } from "./component-input-table.js";
21
+ import type { FilePointer } from "@sealcode/file-manager";
22
+ import { ComponentInputSingleReference } from "./component-input-single-reference.js";
23
+ import { is, predicates } from "@sealcode/ts-predicates";
24
+
25
+ export const actionName = "Components";
26
+ const absoluteUrlPattern = "http(s?)(://)((www.)?)(([^.]+).)?([a-zA-z0-9-_]+)";
27
+
28
+ export async function ComponentInput<State extends JDDPageState, T>({
29
+ ctx,
30
+ state,
31
+ arg_path,
32
+ arg,
33
+ value,
34
+ page,
35
+ makeJDDContext,
36
+ makeAssetURL,
37
+ }: {
38
+ state: State;
39
+ ctx: Context;
40
+ arg_path: string[];
41
+ arg: ComponentArgument<T>;
42
+ value: T;
43
+ page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
44
+ makeJDDContext: (ctx: Context) => JDDContext;
45
+ makeAssetURL: (asset: string) => string;
46
+ }): Promise<string> {
47
+ if (value === undefined) {
48
+ value = await arg.getEmptyValue(makeJDDContext(ctx));
49
+ }
50
+ if (arg instanceof List) {
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
+ return ComponentInputList({
53
+ ctx,
54
+ state,
55
+ arg_path,
56
+ arg,
57
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
58
+ value: value as T[],
59
+ page,
60
+ makeJDDContext,
61
+ makeAssetURL,
62
+ });
63
+ }
64
+
65
+ const argType = arg.getTypeName();
66
+ const isUrlAbsolute =
67
+ arg instanceof ComponentArguments.URL && arg.urlType === "absolute";
68
+ const inputType = isUrlAbsolute ? "url" : "text";
69
+
70
+ if (arg instanceof Structured) {
71
+ return ComponentInputStructured({
72
+ ctx,
73
+ state,
74
+ arg_path,
75
+ arg,
76
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
77
+ value: value as Record<string, unknown>,
78
+ page,
79
+ makeJDDContext,
80
+ makeAssetURL,
81
+ });
82
+ }
83
+
84
+ if (arg instanceof SingleReference) {
85
+ return ComponentInputSingleReference({
86
+ ctx,
87
+ state,
88
+ arg_path,
89
+ arg,
90
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
91
+ value: value as string,
92
+ onchange: page.rerender(),
93
+ makeJDDContext,
94
+ });
95
+ }
96
+
97
+ if (arg instanceof Enum) {
98
+ return ComponentInputEnum({
99
+ state,
100
+ arg_path,
101
+ arg,
102
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
103
+ value: value as string,
104
+ onchange: page.rerender(),
105
+ });
106
+ }
107
+
108
+ if (arg instanceof Image) {
109
+ return ComponentInputImage({
110
+ ctx,
111
+ state,
112
+ arg_path,
113
+ arg,
114
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
115
+ value: value as FilePointer,
116
+ page,
117
+ makeJDDContext,
118
+ });
119
+ }
120
+
121
+ if (arg instanceof Table) {
122
+ return ComponentInputTable({
123
+ ctx,
124
+ state,
125
+ arg_path,
126
+ arg,
127
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
128
+ value: value as TableData<unknown, unknown>,
129
+ page,
130
+ makeJDDContext,
131
+ makeAssetURL,
132
+ });
133
+ }
134
+
135
+ return /* HTML */ `<div>
136
+ <label>
137
+ ${arg_path.at(-1) || ""}
138
+ ${argType == "markdown"
139
+ ? /* HTML */ `<div class="grow-wrap">
140
+ <textarea
141
+ name="${`$${printArgPath(arg_path)}`}"
142
+ onblur="${page.rerender()}"
143
+ cols="40"
144
+ data-controller="markdown-textarea submit-on-input"
145
+ data-action="autogrow-textarea#autogrow blur->autogrow-textarea#autogrow resize->autogrow-textarea#autogrow submit-on-input#sendValues focus->submit-on-input#makePermanent blur->submit-on-input#makeNotPermanent"
146
+ autocomplete="off"
147
+ >
148
+ ${is(value, predicates.string) ? value : ""}
149
+ </textarea
150
+ >
151
+ </div>`
152
+ : /* HTML */ `<input type="${inputType}"
153
+ name="${`$${printArgPath(arg_path)}`}"
154
+ value="${is(value, predicates.string) ? value : ""}" size="40"
155
+ ${isUrlAbsolute ? `pattern="${absoluteUrlPattern}"` : ""}" />`}
156
+ </label>
157
+ </div>`;
158
+ }
@@ -0,0 +1,3 @@
1
+ export function printArgPath(path: string[]): string {
2
+ return path.map((e) => `[${e}]`).join("");
3
+ }