@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,520 @@
1
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
2
+ import type { Registry, TableData } from "@sealcode/jdd";
3
+ import { List, Table } from "@sealcode/jdd";
4
+ import { isTableData, isTableRegularRow } from "@sealcode/jdd";
5
+ import objectPath from "object-path";
6
+ import type { JDDPageState } from "./jdd-page.js";
7
+ import type { StatefulPageActionArgument } from "@sealcode/sealgen";
8
+ import type JDDPage from "./jdd-page.js";
9
+
10
+ function moveElement<T>(
11
+ array: Array<T>,
12
+ fromIndex: number,
13
+ toIndex: number
14
+ ): Array<T> {
15
+ const element = array.splice(fromIndex, 1)[0];
16
+ array.splice(toIndex, 0, element as T);
17
+ return array;
18
+ }
19
+
20
+ export function getComponentData(
21
+ state: JDDPageState,
22
+ arg_path: string[],
23
+ registry: Registry
24
+ ) {
25
+ const index_arg = arg_path[1];
26
+ if (!index_arg) {
27
+ throw new Error("Missing component index in arg path");
28
+ }
29
+ const component_index = parseInt(index_arg);
30
+ const component_args = state.components[component_index]?.args || {};
31
+ const component_name =
32
+ state.components[component_index]?.component_name || "";
33
+ const component = registry.get(component_name);
34
+ const arg_path_within_component = arg_path.slice(3); // remove "components" and the index of the component and "args"
35
+
36
+ const [argument, , argument_value] = component?.getArgumentAtPath(
37
+ arg_path_within_component,
38
+ component_args
39
+ ) || [null, null, null];
40
+
41
+ return {
42
+ component_index,
43
+ component_args,
44
+ component_name,
45
+ component,
46
+ argument,
47
+ argument_value,
48
+ arg_path_within_component,
49
+ };
50
+ }
51
+
52
+ export const ComponentPreviewActions = <const>{
53
+ add_array_item: async ({
54
+ ctx,
55
+ state,
56
+ args: [arg_path],
57
+ page,
58
+ }: StatefulPageActionArgument<JDDPageState, [string[]]>) => {
59
+ const {
60
+ component_name,
61
+ component,
62
+ argument,
63
+ arg_path_within_component,
64
+ argument_value,
65
+ } = getComponentData(state, arg_path, (page as JDDPage).registry);
66
+ if (!component) {
67
+ console.error("unknown component: ", component_name);
68
+ return state;
69
+ }
70
+ if (!argument) {
71
+ console.error(
72
+ "Didn't find a list argument at this path",
73
+ arg_path_within_component
74
+ );
75
+ return state;
76
+ }
77
+ if (!(argument instanceof List)) {
78
+ throw new Error(
79
+ `Expected argument in path ${arg_path.join(
80
+ "."
81
+ )} to be an instance of List`
82
+ );
83
+ }
84
+ objectPath.insert(
85
+ state,
86
+ arg_path,
87
+ await argument.item_type.getExampleValue(
88
+ (page as JDDPage).makeJDDContext(ctx)
89
+ ),
90
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
91
+ Array.isArray(argument_value) ? argument_value.length : 0
92
+ );
93
+ return state;
94
+ },
95
+
96
+ remove_array_item: ({
97
+ state,
98
+ args: [arg_path, index_to_remove],
99
+ }: StatefulPageActionArgument<
100
+ JDDPageState,
101
+ [string[], number]
102
+ >): JDDPageState => {
103
+ objectPath.del(state, [...arg_path, index_to_remove]);
104
+ return state;
105
+ },
106
+
107
+ move_array_item_up: async ({
108
+ state,
109
+ args: [arg_path, element_index],
110
+ }: StatefulPageActionArgument<
111
+ JDDPageState,
112
+ [string[], number]
113
+ >): Promise<JDDPageState> => {
114
+ const array_values = objectPath.get(state, arg_path) as unknown[];
115
+ const curr = array_values[element_index];
116
+ const prev = array_values[element_index - 1];
117
+ if (!prev || !curr) {
118
+ throw new Error("No element at such index or cannot move it up");
119
+ }
120
+ [array_values[element_index - 1], array_values[element_index]] = [
121
+ curr,
122
+ prev,
123
+ ];
124
+ return state;
125
+ },
126
+
127
+ move_array_item_down: async ({
128
+ state,
129
+ args: [arg_path, element_index],
130
+ }: StatefulPageActionArgument<
131
+ JDDPageState,
132
+ [string[], number]
133
+ >): Promise<JDDPageState> => {
134
+ const array_values = objectPath.get(state, arg_path) as unknown[];
135
+ const curr = array_values[element_index];
136
+ const next = array_values[element_index + 1];
137
+ if (!next || !curr) {
138
+ throw new Error("No element at such index or cannot move it up");
139
+ }
140
+ [array_values[element_index], array_values[element_index + 1]] = [
141
+ next,
142
+ curr,
143
+ ];
144
+ return state;
145
+ },
146
+
147
+ change_component: async ({
148
+ ctx,
149
+ inputs,
150
+ state,
151
+ page,
152
+ }: StatefulPageActionArgument<JDDPageState, []>): Promise<JDDPageState> => {
153
+ const component_name = inputs.component;
154
+ if (!component_name || typeof component_name !== "string") {
155
+ throw new Error(
156
+ "Missing input: 'component' for action change_component. It should contain the name of the new component type"
157
+ );
158
+ }
159
+ const component = (page as JDDPage).registry.get(component_name);
160
+ if (!component) {
161
+ throw new Error(
162
+ `Unknown or disallowed component name: ${component_name}`
163
+ );
164
+ }
165
+ return {
166
+ ...state,
167
+ components: [
168
+ {
169
+ component_name: component_name,
170
+ args:
171
+ (await component?.getExampleValues(
172
+ (page as JDDPage).makeJDDContext(ctx)
173
+ )) || {},
174
+ },
175
+ ],
176
+ };
177
+ },
178
+
179
+ randomize_args: async ({
180
+ ctx,
181
+ state,
182
+ page,
183
+ args: [component_index_str],
184
+ }: StatefulPageActionArgument<
185
+ JDDPageState,
186
+ [string]
187
+ >): Promise<JDDPageState> => {
188
+ const { component_index, component } = getComponentData(
189
+ state,
190
+ ["components", component_index_str],
191
+ (page as JDDPage).registry
192
+ );
193
+
194
+ const component_data = state.components[component_index];
195
+ if (!component_data) {
196
+ throw new Error("Missing component data");
197
+ }
198
+ component_data.args =
199
+ (await component?.getExampleValues(
200
+ (page as JDDPage).makeJDDContext(ctx)
201
+ )) || {};
202
+ return {
203
+ ...state,
204
+ };
205
+ },
206
+
207
+ add_table_row: async ({
208
+ ctx,
209
+ state,
210
+ page,
211
+ args: [arg_path, columns, type = "row"],
212
+ }: StatefulPageActionArgument<
213
+ JDDPageState,
214
+ [string[], number, "header" | "row" | undefined]
215
+ >) => {
216
+ const jdd_context = (page as JDDPage).makeJDDContext(ctx);
217
+ const { component_args, argument } = getComponentData(
218
+ state,
219
+ arg_path,
220
+ (page as JDDPage).registry
221
+ );
222
+ let row;
223
+
224
+ if (!argument) {
225
+ console.error("Unknown component at path", arg_path);
226
+ return state;
227
+ }
228
+ if (!(argument instanceof Table)) {
229
+ throw new Error(
230
+ `Expected argument at path ${arg_path.join(
231
+ "."
232
+ )} to be of type Table`
233
+ );
234
+ }
235
+ if (type == "header") {
236
+ row = {
237
+ type: "header",
238
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
239
+ header_content: await argument.header_type.getExampleValue(
240
+ jdd_context
241
+ ),
242
+ };
243
+ } else {
244
+ const cells = [];
245
+ for (let i = 0; i < columns; i++) {
246
+ cells.push(
247
+ // eslint-disable-next-line no-await-in-loop
248
+ await argument.cell_type.getExampleValue(jdd_context)
249
+ );
250
+ }
251
+ row = { type: "row", cells };
252
+ }
253
+ objectPath.push(state, [...arg_path, "rows"], row);
254
+ return state;
255
+ },
256
+
257
+ add_table_column: async ({
258
+ ctx,
259
+ state,
260
+ page,
261
+ args: [arg_path],
262
+ }: StatefulPageActionArgument<JDDPageState, [string[]]>) => {
263
+ const { argument } = getComponentData(
264
+ state,
265
+ arg_path,
266
+ (page as JDDPage).registry
267
+ ) as unknown as {
268
+ argument: Table<unknown, unknown>;
269
+ };
270
+ if (!argument) {
271
+ console.error("Unknown component at path", arg_path);
272
+ return state;
273
+ }
274
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
275
+ const tableData: TableData<unknown, unknown> = objectPath.get(
276
+ state,
277
+ arg_path
278
+ );
279
+ if (!isTableData(tableData)) {
280
+ throw new Error("wrong table data");
281
+ }
282
+ // eslint-disable-next-line @typescript-eslint/no-for-in-array
283
+ for (const i in tableData.rows) {
284
+ const row = tableData.rows[i];
285
+ if (isTableRegularRow(row)) {
286
+ row.cells.push(
287
+ // eslint-disable-next-line no-await-in-loop
288
+ await argument.cell_type.getExampleValue(
289
+ (page as JDDPage).makeJDDContext(ctx)
290
+ )
291
+ );
292
+ }
293
+ }
294
+ objectPath.set(state, arg_path, tableData);
295
+ console.log("NEW STATE AFTER ADDING THE COLUN");
296
+ console.dir(state, { depth: 10 });
297
+ return state;
298
+ },
299
+
300
+ remove_table_column: ({
301
+ state,
302
+ args: [arg_path, column_index_to_remove],
303
+ }: StatefulPageActionArgument<
304
+ JDDPageState,
305
+ [string[], number]
306
+ >): JDDPageState => {
307
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
308
+ const tableData: TableData<unknown, unknown> = objectPath.get(
309
+ state,
310
+ arg_path
311
+ );
312
+ if (!isTableData(tableData)) {
313
+ throw new Error("wrong table data");
314
+ }
315
+ // eslint-disable-next-line @typescript-eslint/no-for-in-array
316
+ for (const i in tableData.rows) {
317
+ const row = tableData.rows[i];
318
+ if (isTableRegularRow(row)) {
319
+ row.cells = row.cells.filter(
320
+ (_, i) => i != column_index_to_remove
321
+ );
322
+ }
323
+ }
324
+ objectPath.set(state, arg_path, tableData);
325
+ return state;
326
+ },
327
+
328
+ remove_table_row: ({
329
+ state,
330
+ args: [arg_path, row_index],
331
+ }: StatefulPageActionArgument<
332
+ JDDPageState,
333
+ [string[], number]
334
+ >): JDDPageState => {
335
+ objectPath.del(state, [...arg_path, "rows", row_index]);
336
+ return state;
337
+ },
338
+
339
+ move_table_column_right: ({
340
+ state,
341
+ page,
342
+ args: [arg_path, column_index],
343
+ }: StatefulPageActionArgument<JDDPageState, [string[], number]>) => {
344
+ const { component_args } = getComponentData(
345
+ state,
346
+ arg_path,
347
+ (page as JDDPage).registry
348
+ );
349
+
350
+ const last_path_element = arg_path.at(-1);
351
+ if (!last_path_element) {
352
+ throw new Error("arg path is empty");
353
+ }
354
+ const data = objectPath.get<unknown>(
355
+ component_args,
356
+ last_path_element,
357
+ ""
358
+ );
359
+ if (!isTableData(data)) {
360
+ throw new Error(
361
+ "Expected arg value for a table to be properly shaped"
362
+ );
363
+ }
364
+ for (const row of data.rows) {
365
+ if (row.type == "row") {
366
+ moveElement(row.cells, column_index, column_index + 1);
367
+ }
368
+ }
369
+ objectPath.set(state, [...arg_path, "rows"], data.rows);
370
+ return state;
371
+ },
372
+
373
+ move_table_row_down: ({
374
+ state,
375
+ page,
376
+ args: [arg_path, row_index],
377
+ }: StatefulPageActionArgument<JDDPageState, [string[], number]>) => {
378
+ const { component_args } = getComponentData(
379
+ state,
380
+ arg_path,
381
+ (page as JDDPage).registry
382
+ );
383
+ const last_path_element = arg_path.at(-1);
384
+ if (!last_path_element) {
385
+ throw new Error("arg path is empty");
386
+ }
387
+ const data = objectPath.get<unknown>(
388
+ component_args,
389
+ last_path_element,
390
+ ""
391
+ );
392
+ if (!isTableData(data)) {
393
+ throw new Error(
394
+ "Expected arg value for a table to be properly shaped"
395
+ );
396
+ }
397
+ moveElement(data.rows, row_index, row_index + 1);
398
+ objectPath.set(state, [...arg_path, "rows"], data.rows);
399
+ return state;
400
+ },
401
+
402
+ change_size: ({
403
+ state,
404
+ inputs,
405
+ }: StatefulPageActionArgument<JDDPageState>) => {
406
+ return {
407
+ ...state,
408
+ preview_size: inputs.size,
409
+ };
410
+ },
411
+
412
+ add_component: async ({
413
+ ctx,
414
+ state,
415
+ inputs,
416
+ page,
417
+ }: StatefulPageActionArgument<JDDPageState, []>): Promise<JDDPageState> => {
418
+ const component_name = inputs.component;
419
+ if (!component_name) {
420
+ throw new Error("Missing component name");
421
+ }
422
+ const component = (page as JDDPage).registry.get(component_name);
423
+
424
+ return {
425
+ ...state,
426
+ components: [
427
+ ...state.components,
428
+ {
429
+ component_name: component_name,
430
+ args:
431
+ (await component?.getExampleValues(
432
+ (page as JDDPage).makeJDDContext(ctx)
433
+ )) || {},
434
+ },
435
+ ],
436
+ };
437
+ },
438
+
439
+ remove_component: async ({
440
+ state,
441
+ args: [component_index],
442
+ }: StatefulPageActionArgument<
443
+ JDDPageState,
444
+ [number]
445
+ >): Promise<JDDPageState> => {
446
+ const newComponentState = [...state.components];
447
+ newComponentState.splice(component_index, 1);
448
+ return {
449
+ ...state,
450
+ components: newComponentState,
451
+ };
452
+ },
453
+
454
+ move_component_up: async ({
455
+ state,
456
+ args: [component_index],
457
+ }: StatefulPageActionArgument<
458
+ JDDPageState,
459
+ [number]
460
+ >): Promise<JDDPageState> => {
461
+ const newComps = [...state.components];
462
+ const prev = newComps[component_index - 1];
463
+ const curr = newComps[component_index];
464
+ if (!prev || !curr) {
465
+ throw new Error("No component at such index or cannot move it up");
466
+ }
467
+ [newComps[component_index], newComps[component_index - 1]] = [
468
+ prev,
469
+ curr,
470
+ ];
471
+ return { ...state, components: newComps };
472
+ },
473
+
474
+ move_component_down: async ({
475
+ state,
476
+ args: [component_index],
477
+ }: StatefulPageActionArgument<
478
+ JDDPageState,
479
+ [number]
480
+ >): Promise<JDDPageState> => {
481
+ const newComps = [...state.components];
482
+ const next = newComps[component_index + 1];
483
+ const curr = newComps[component_index];
484
+ if (!next || !curr) {
485
+ throw new Error("No component at such index or cannot move it up");
486
+ }
487
+ [newComps[component_index], newComps[component_index + 1]] = [
488
+ next,
489
+ curr,
490
+ ];
491
+ return { ...state, components: newComps };
492
+ },
493
+
494
+ remove_file: async ({
495
+ state,
496
+ args: [arg_path],
497
+ }: StatefulPageActionArgument<
498
+ JDDPageState,
499
+ [string[]]
500
+ >): Promise<JDDPageState> => {
501
+ objectPath.set(state, arg_path, null);
502
+ return state;
503
+ },
504
+
505
+ replace_state: async ({
506
+ ctx,
507
+ state,
508
+ inputs,
509
+ page,
510
+ }: StatefulPageActionArgument<JDDPageState>) => {
511
+ const new_state = await (page as JDDPage).deserializeState(
512
+ ctx,
513
+ inputs["state_override"] || "{}"
514
+ );
515
+ return {
516
+ ...new_state,
517
+ preview_size: state.preview_size,
518
+ };
519
+ },
520
+ };
@@ -0,0 +1,100 @@
1
+ import { documentContainerFromParsed, JDD } from "@sealcode/jdd";
2
+ import type { Context } from "koa";
3
+ import type { Templatable } from "tempstream";
4
+ import { tempstream } from "tempstream";
5
+ import type { Stringifiable } from "tempstream/@types/stringify.js";
6
+ import { ComponentPreviewActions } from "./component-preview-actions.js";
7
+ import type { JDDPageState } from "./jdd-page.js";
8
+ import JDDPage from "./jdd-page.js";
9
+
10
+ export class JDDDebugger extends JDDPage {
11
+ renderParameterButtons(state: JDDPageState): Stringifiable {
12
+ const all_components = super.getRegistryComponents();
13
+ if (!state.components[0]) {
14
+ console.error("No components are present in state.components");
15
+ }
16
+ return /* HTML */ `<div>
17
+ <input type="submit" value="Preview" />
18
+ <select
19
+ name="component"
20
+ onchange="${this.makeActionCallback("change_component")}"
21
+ autocomplete="off"
22
+ >
23
+ ${Object.entries(all_components)
24
+ .map(
25
+ ([name]) => /* HTML */ `<option
26
+ value="${name}"
27
+ ${name == state.components[0]?.component_name
28
+ ? "selected"
29
+ : ""}
30
+ >
31
+ ${name}
32
+ </option>`
33
+ )
34
+ .join("")}
35
+ </select>
36
+ <noscript>
37
+ ${this.makeActionButton(state, "change_component")}
38
+ </noscript>
39
+ ${this.makeActionButton(state, "randomize_args", "0")}
40
+ </div>`;
41
+ }
42
+ actions = ComponentPreviewActions;
43
+
44
+ async getInitialState(ctx: Context) {
45
+ const first_component = Object.entries(this.registry.getAll())[0];
46
+ if (!first_component) {
47
+ throw new Error("No registered components!");
48
+ }
49
+ const [component_name, component] = first_component;
50
+ const initial_state = {
51
+ components: [
52
+ {
53
+ component_name: component_name,
54
+ args: await component.getExampleValues(
55
+ this.makeJDDContext(ctx)
56
+ ),
57
+ open: true,
58
+ },
59
+ ],
60
+ };
61
+ return initial_state;
62
+ }
63
+
64
+ wrapInLayout(
65
+ ctx: Context,
66
+ content: Templatable,
67
+ state: JDDPageState
68
+ ): Templatable {
69
+ const jdd = new JDD(
70
+ this.registry,
71
+ this.makeJDDContext(ctx),
72
+ documentContainerFromParsed(state.components)
73
+ );
74
+ return this.html({
75
+ ctx,
76
+ title: "Components",
77
+ body: content,
78
+ description: "",
79
+ css_clumps: ["jdd-page", ...jdd.getAllCSSClumps()],
80
+ htmlOptions: {
81
+ morphing: true,
82
+ preserveScroll: true,
83
+ autoRefreshCSS: true,
84
+ showBanner: false,
85
+ navbar: () => ``,
86
+ bodyClasses: ["jdd-editor"],
87
+ showBottomNavbar: false,
88
+ showFooter: false,
89
+ loadHamburgerMenu: false,
90
+ loadSearchModal: false,
91
+ },
92
+ makeHead: (...args: unknown[]) =>
93
+ tempstream`${this.defaultHead(
94
+ ...args
95
+ )}${jdd.renderEarlyAssets()}`,
96
+ });
97
+ }
98
+
99
+ containerSizes = ["320", "600", "800", "1024", "1300", "1920"];
100
+ }
@@ -0,0 +1,13 @@
1
+ /* eslint-disable @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-assignment */
2
+ import { Controller } from "stimulus";
3
+
4
+ export default class AutogrowTextarea extends Controller<HTMLTextAreaElement> {
5
+ connect() {
6
+ this.autogrow();
7
+ }
8
+
9
+ autogrow() {
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
11
+ (this.element.parentNode as any).dataset.replicatedValue = this.element.value;
12
+ }
13
+ }