@fc3/mmcadi 0.1.63 → 0.1.65

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 (121) hide show
  1. package/dist/.last-compile-time +1 -1
  2. package/dist/.last-publish-time +1 -1
  3. package/dist/client.js +485 -184
  4. package/dist/src/client/helper/interaction.d.ts +0 -1
  5. package/dist/src/client/helper/interaction.js +3 -28
  6. package/dist/src/client/helper/interaction.js.map +1 -1
  7. package/dist/src/client/page/cursor.d.ts +3 -0
  8. package/dist/src/client/page/cursor.js +72 -37
  9. package/dist/src/client/page/cursor.js.map +1 -1
  10. package/dist/src/client/page/edit-block.d.ts +11 -0
  11. package/dist/src/client/page/edit-block.js +192 -7
  12. package/dist/src/client/page/edit-block.js.map +1 -1
  13. package/dist/src/client/page/select-block-type.d.ts +1 -1
  14. package/dist/src/client/page/select-block-type.js +34 -22
  15. package/dist/src/client/page/select-block-type.js.map +1 -1
  16. package/dist/src/client/page.js +2 -0
  17. package/dist/src/client/page.js.map +1 -1
  18. package/dist/src/client/utility/recompute-index-paths.d.ts +2 -0
  19. package/dist/src/client/utility/recompute-index-paths.js +24 -0
  20. package/dist/src/client/utility/recompute-index-paths.js.map +1 -0
  21. package/dist/src/common/builder/block/input.d.ts +3 -0
  22. package/dist/src/common/builder/block/input.js +18 -0
  23. package/dist/src/common/builder/block/input.js.map +1 -0
  24. package/dist/src/common/utility/decrement-index-path.d.ts +2 -0
  25. package/dist/src/common/utility/decrement-index-path.js +26 -0
  26. package/dist/src/common/utility/decrement-index-path.js.map +1 -0
  27. package/dist/src/common/utility/get-input-character-for-block-type.d.ts +3 -0
  28. package/dist/src/common/utility/get-input-character-for-block-type.js +42 -0
  29. package/dist/src/common/utility/get-input-character-for-block-type.js.map +1 -0
  30. package/dist/src/common/utility/get-last-index-path-segment.d.ts +2 -0
  31. package/dist/src/common/utility/get-last-index-path-segment.js +17 -0
  32. package/dist/src/common/utility/get-last-index-path-segment.js.map +1 -0
  33. package/dist/src/common/utility/get-parent-index-path.d.ts +2 -0
  34. package/dist/src/common/utility/get-parent-index-path.js +17 -0
  35. package/dist/src/common/utility/get-parent-index-path.js.map +1 -0
  36. package/dist/src/common/utility/increment-index-path.d.ts +2 -0
  37. package/dist/src/common/utility/increment-index-path.js +18 -0
  38. package/dist/src/common/utility/increment-index-path.js.map +1 -0
  39. package/dist/src/enum/action-type.d.ts +1 -0
  40. package/dist/src/enum/action-type.js +1 -0
  41. package/dist/src/enum/action-type.js.map +1 -1
  42. package/dist/src/enum/block-type.d.ts +3 -1
  43. package/dist/src/enum/block-type.js +2 -0
  44. package/dist/src/enum/block-type.js.map +1 -1
  45. package/dist/src/enum/emoji.d.ts +5 -1
  46. package/dist/src/enum/emoji.js +4 -0
  47. package/dist/src/enum/emoji.js.map +1 -1
  48. package/dist/src/index.d.ts +1 -0
  49. package/dist/src/index.js +3 -1
  50. package/dist/src/index.js.map +1 -1
  51. package/dist/src/server/endpoint/abstract-page.d.ts +0 -2
  52. package/dist/src/server/endpoint/abstract-page.js +0 -11
  53. package/dist/src/server/endpoint/abstract-page.js.map +1 -1
  54. package/dist/src/server/endpoint/action/create.d.ts +1 -0
  55. package/dist/src/server/endpoint/action/create.js +122 -33
  56. package/dist/src/server/endpoint/action/create.js.map +1 -1
  57. package/dist/src/server/endpoint/action/get.d.ts +0 -2
  58. package/dist/src/server/endpoint/action/get.js +32 -16
  59. package/dist/src/server/endpoint/action/get.js.map +1 -1
  60. package/dist/src/server/endpoint/base.d.ts +4 -0
  61. package/dist/src/server/endpoint/base.js +20 -0
  62. package/dist/src/server/endpoint/base.js.map +1 -1
  63. package/dist/src/server/endpoint/playlist/get.d.ts +0 -2
  64. package/dist/src/server/endpoint/playlist/get.js +1 -16
  65. package/dist/src/server/endpoint/playlist/get.js.map +1 -1
  66. package/dist/src/server/endpoint/settings/get.d.ts +0 -2
  67. package/dist/src/server/endpoint/settings/get.js +2 -19
  68. package/dist/src/server/endpoint/settings/get.js.map +1 -1
  69. package/dist/src/server/factory/block-serializer.js +6 -0
  70. package/dist/src/server/factory/block-serializer.js.map +1 -1
  71. package/dist/src/server/middleware/error-handler.js +2 -1
  72. package/dist/src/server/middleware/error-handler.js.map +1 -1
  73. package/dist/src/server/operation/create-session.js +2 -2
  74. package/dist/src/server/operation/create-session.js.map +1 -1
  75. package/dist/src/server/operation/delete-block.d.ts +1 -0
  76. package/dist/src/server/operation/delete-block.js +16 -2
  77. package/dist/src/server/operation/delete-block.js.map +1 -1
  78. package/dist/src/server/operation/load-block.js +12 -2
  79. package/dist/src/server/operation/load-block.js.map +1 -1
  80. package/dist/src/server/operation/load-page.d.ts +0 -2
  81. package/dist/src/server/operation/load-page.js +27 -38
  82. package/dist/src/server/operation/load-page.js.map +1 -1
  83. package/dist/src/server/operation/move-block.d.ts +1 -0
  84. package/dist/src/server/operation/move-block.js +20 -3
  85. package/dist/src/server/operation/move-block.js.map +1 -1
  86. package/dist/src/server/operation/reposition-block.d.ts +5 -7
  87. package/dist/src/server/operation/reposition-block.js +48 -76
  88. package/dist/src/server/operation/reposition-block.js.map +1 -1
  89. package/dist/src/server/serializer/action.d.ts +7 -0
  90. package/dist/src/server/serializer/action.js +223 -61
  91. package/dist/src/server/serializer/action.js.map +1 -1
  92. package/dist/src/server/serializer/base.js +1 -1
  93. package/dist/src/server/serializer/block/button.d.ts +6 -0
  94. package/dist/src/server/serializer/block/button.js +27 -0
  95. package/dist/src/server/serializer/block/button.js.map +1 -0
  96. package/dist/src/server/serializer/block/input.d.ts +6 -0
  97. package/dist/src/server/serializer/block/input.js +44 -0
  98. package/dist/src/server/serializer/block/input.js.map +1 -0
  99. package/dist/src/server/serializer/block.js +20 -16
  100. package/dist/src/server/serializer/block.js.map +1 -1
  101. package/dist/src/server/serializer/page.js +6 -1
  102. package/dist/src/server/serializer/page.js.map +1 -1
  103. package/dist/src/server/utility/account-has-block-permission.d.ts +6 -0
  104. package/dist/src/server/utility/account-has-block-permission.js +24 -0
  105. package/dist/src/server/utility/account-has-block-permission.js.map +1 -0
  106. package/dist/src/server/utility/get-emoji-for-block-type.js +29 -29
  107. package/dist/src/server/utility/get-emoji-for-block-type.js.map +1 -1
  108. package/dist/src/server/utility/get-siblings-and-index-for-index-path.js +23 -29
  109. package/dist/src/server/utility/get-siblings-and-index-for-index-path.js.map +1 -1
  110. package/dist/src/server.js +1 -1
  111. package/dist/src/server.js.map +1 -1
  112. package/dist/src/type/action/add-block.d.ts +11 -1
  113. package/dist/src/type/block/button.d.ts +7 -0
  114. package/dist/src/type/block/button.js +3 -0
  115. package/dist/src/type/block/button.js.map +1 -0
  116. package/dist/src/type/block/input.d.ts +7 -0
  117. package/dist/src/type/block/input.js +3 -0
  118. package/dist/src/type/block/input.js.map +1 -0
  119. package/dist/src/type/block.d.ts +2 -0
  120. package/dist/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -259,9 +259,9 @@
259
259
  };
260
260
  Object.defineProperty(exports, "__esModule", { value: true });
261
261
  var generic_1 = __importDefault(require_generic());
262
- var InvariantViolation14 = class extends generic_1.default {
262
+ var InvariantViolation17 = class extends generic_1.default {
263
263
  };
264
- exports.default = InvariantViolation14;
264
+ exports.default = InvariantViolation17;
265
265
  }
266
266
  });
267
267
 
@@ -968,18 +968,18 @@
968
968
  "node_modules/@fc3/time/dist/src/enum/time-interval.js"(exports) {
969
969
  "use strict";
970
970
  Object.defineProperty(exports, "__esModule", { value: true });
971
- var TimeInterval3;
972
- (function(TimeInterval4) {
973
- TimeInterval4[TimeInterval4["ONE_FRAME"] = 16] = "ONE_FRAME";
974
- TimeInterval4[TimeInterval4["ONE_SECOND"] = 1e3] = "ONE_SECOND";
975
- TimeInterval4[TimeInterval4["ONE_MINUTE"] = 6e4] = "ONE_MINUTE";
976
- TimeInterval4[TimeInterval4["ONE_HOUR"] = 36e5] = "ONE_HOUR";
977
- TimeInterval4[TimeInterval4["ONE_DAY"] = 864e5] = "ONE_DAY";
978
- TimeInterval4[TimeInterval4["ONE_WEEK"] = 6048e5] = "ONE_WEEK";
979
- TimeInterval4[TimeInterval4["ONE_MONTH"] = 2592e6] = "ONE_MONTH";
980
- TimeInterval4[TimeInterval4["ONE_YEAR"] = 31536e6] = "ONE_YEAR";
981
- })(TimeInterval3 || (TimeInterval3 = {}));
982
- exports.default = TimeInterval3;
971
+ var TimeInterval4;
972
+ (function(TimeInterval5) {
973
+ TimeInterval5[TimeInterval5["ONE_FRAME"] = 16] = "ONE_FRAME";
974
+ TimeInterval5[TimeInterval5["ONE_SECOND"] = 1e3] = "ONE_SECOND";
975
+ TimeInterval5[TimeInterval5["ONE_MINUTE"] = 6e4] = "ONE_MINUTE";
976
+ TimeInterval5[TimeInterval5["ONE_HOUR"] = 36e5] = "ONE_HOUR";
977
+ TimeInterval5[TimeInterval5["ONE_DAY"] = 864e5] = "ONE_DAY";
978
+ TimeInterval5[TimeInterval5["ONE_WEEK"] = 6048e5] = "ONE_WEEK";
979
+ TimeInterval5[TimeInterval5["ONE_MONTH"] = 2592e6] = "ONE_MONTH";
980
+ TimeInterval5[TimeInterval5["ONE_YEAR"] = 31536e6] = "ONE_YEAR";
981
+ })(TimeInterval4 || (TimeInterval4 = {}));
982
+ exports.default = TimeInterval4;
983
983
  }
984
984
  });
985
985
 
@@ -1725,7 +1725,7 @@
1725
1725
  });
1726
1726
 
1727
1727
  // src/client/client.ts
1728
- var import_errors14 = __toESM(require_src2());
1728
+ var import_errors17 = __toESM(require_src2());
1729
1729
 
1730
1730
  // src/client/enum/page-type.ts
1731
1731
  var PageType = /* @__PURE__ */ ((PageType2) => {
@@ -1927,6 +1927,7 @@
1927
1927
  BlockType2["FOLDER"] = "folder";
1928
1928
  BlockType2["MULTI_COLUMN"] = "multi_column";
1929
1929
  BlockType2["LINK"] = "link";
1930
+ BlockType2["INPUT"] = "input";
1930
1931
  BlockType2["TODO"] = "todo";
1931
1932
  BlockType2["LIST"] = "list";
1932
1933
  BlockType2["REDIRECT"] = "redirect";
@@ -1935,6 +1936,7 @@
1935
1936
  BlockType2["PARAMETER"] = "parameter";
1936
1937
  BlockType2["CARD"] = "card";
1937
1938
  BlockType2["TABLE"] = "table";
1939
+ BlockType2["BUTTON"] = "button";
1938
1940
  return BlockType2;
1939
1941
  })(BlockType || {});
1940
1942
  var block_type_default = BlockType;
@@ -2130,44 +2132,94 @@
2130
2132
  var year_default = YearPage;
2131
2133
 
2132
2134
  // src/client/page/select-block-type.ts
2135
+ var import_errors5 = __toESM(require_src2());
2136
+
2137
+ // src/common/utility/get-input-character-for-block-type.ts
2133
2138
  var import_errors4 = __toESM(require_src2());
2139
+ var BlockTypeCharacters = {
2140
+ [block_type_default.HEADER]: "h",
2141
+ [block_type_default.NOTE]: "n",
2142
+ [block_type_default.IMAGE]: "i",
2143
+ [block_type_default.VIDEO]: "v",
2144
+ [block_type_default.AUDIO]: "a",
2145
+ [block_type_default.EPHEMERAL]: "",
2146
+ [block_type_default.CALENDAR]: "",
2147
+ [block_type_default.DIRECTORY]: "",
2148
+ [block_type_default.FOLDER]: "f",
2149
+ [block_type_default.MULTI_COLUMN]: "m",
2150
+ [block_type_default.LINK]: "l",
2151
+ [block_type_default.INPUT]: "x",
2152
+ [block_type_default.TODO]: "t",
2153
+ [block_type_default.LIST]: "",
2154
+ [block_type_default.REDIRECT]: "r",
2155
+ [block_type_default.BACKGROUND]: "b",
2156
+ [block_type_default.WHITESPACE]: "w",
2157
+ [block_type_default.PARAMETER]: "p",
2158
+ [block_type_default.CARD]: "c",
2159
+ [block_type_default.TABLE]: "",
2160
+ [block_type_default.BUTTON]: ""
2161
+ };
2162
+ function getInputCharacterForBlockType(block_type) {
2163
+ const character = BlockTypeCharacters[block_type];
2164
+ if (character === void 0) {
2165
+ throw new import_errors4.InvariantViolation(`
2166
+ Tried to read input character for block type "${block_type}",
2167
+ but it was not set
2168
+ `);
2169
+ }
2170
+ return character;
2171
+ }
2172
+ var get_input_character_for_block_type_default = getInputCharacterForBlockType;
2173
+
2174
+ // src/client/page/select-block-type.ts
2175
+ function getKeyCodeForCharacter(character) {
2176
+ const uppercase_character = character.toUpperCase();
2177
+ const entries = Object.entries(key_code_default);
2178
+ const entry = entries.find((entry2) => {
2179
+ const [key, _2] = entry2;
2180
+ return key === uppercase_character;
2181
+ });
2182
+ if (entry === void 0) {
2183
+ return null;
2184
+ }
2185
+ const [_, value] = entry;
2186
+ return value;
2187
+ }
2188
+ function getKeyCodeForBlockType(block_type) {
2189
+ const input_character = get_input_character_for_block_type_default(block_type);
2190
+ if (input_character === "") {
2191
+ return null;
2192
+ }
2193
+ const keycode = getKeyCodeForCharacter(input_character);
2194
+ return keycode;
2195
+ }
2134
2196
  var SelectBlockTypePage = class extends page_default {
2135
- handleKey(key_code) {
2136
- switch (key_code) {
2137
- case key_code_default.N:
2138
- return this.createBlockOfType(block_type_default.NOTE);
2139
- case key_code_default.I:
2140
- return this.createBlockOfType(block_type_default.IMAGE);
2141
- case key_code_default.A:
2142
- return this.createBlockOfType(block_type_default.AUDIO);
2143
- case key_code_default.T:
2144
- return this.createBlockOfType(block_type_default.TODO);
2145
- case key_code_default.H:
2146
- return this.createBlockOfType(block_type_default.HEADER);
2147
- case key_code_default.F:
2148
- return this.createBlockOfType(block_type_default.FOLDER);
2149
- case key_code_default.L:
2150
- return this.createBlockOfType(block_type_default.LINK);
2151
- case key_code_default.M:
2152
- return this.createBlockOfType(block_type_default.MULTI_COLUMN);
2153
- case key_code_default.W:
2154
- return this.createBlockOfType(block_type_default.WHITESPACE);
2155
- default:
2156
- return super.handleKey(key_code);
2197
+ handleKey(keycode) {
2198
+ const block_types = Object.values(block_type_default);
2199
+ const found = block_types.some((block_type) => {
2200
+ const block_keycode = getKeyCodeForBlockType(block_type);
2201
+ if (block_keycode !== keycode) {
2202
+ return false;
2203
+ }
2204
+ this.createBlockOfType(block_type);
2205
+ return true;
2206
+ });
2207
+ if (!found) {
2208
+ return super.handleKey(keycode);
2157
2209
  }
2158
2210
  }
2159
2211
  createBlockOfType(block_type) {
2160
2212
  const id = `add-block-${block_type}`;
2161
2213
  const element = document.getElementById(id);
2162
2214
  if (element === null) {
2163
- throw new import_errors4.InvariantViolation(`
2215
+ throw new import_errors5.InvariantViolation(`
2164
2216
  Tried to create block of type ${block_type},
2165
2217
  but the creation link was not found
2166
2218
  `);
2167
2219
  }
2168
2220
  const href = element.getAttribute("href");
2169
2221
  if (href === null) {
2170
- throw new import_errors4.InvariantViolation(`
2222
+ throw new import_errors5.InvariantViolation(`
2171
2223
  Tried to create block of type ${block_type},
2172
2224
  but the creation href was not present on the link element
2173
2225
  `);
@@ -2178,21 +2230,64 @@
2178
2230
  var select_block_type_default = SelectBlockTypePage;
2179
2231
 
2180
2232
  // src/client/page/cursor.ts
2181
- var import_errors9 = __toESM(require_src2());
2233
+ var import_errors12 = __toESM(require_src2());
2182
2234
  var import_array = __toESM(require_src3());
2183
2235
  var import_time2 = __toESM(require_src6());
2184
2236
 
2237
+ // src/enum/action-type.ts
2238
+ var ActionType = /* @__PURE__ */ ((ActionType2) => {
2239
+ ActionType2["PREVIEW_BLOCK"] = "preview_block";
2240
+ ActionType2["ADD_BLOCK"] = "add_block";
2241
+ ActionType2["DELETE_BLOCK"] = "delete_block";
2242
+ ActionType2["MOVE_BLOCK"] = "move_block";
2243
+ ActionType2["HIDE_BLOCK"] = "hide_block";
2244
+ ActionType2["PROMOTE_BLOCK"] = "promote_block";
2245
+ ActionType2["DEMOTE_BLOCK"] = "demote_block";
2246
+ ActionType2["REPOSITION_BLOCK"] = "reposition_block";
2247
+ ActionType2["EDIT_BLOCK"] = "edit_block";
2248
+ ActionType2["CREATE_PAGE"] = "create_page";
2249
+ ActionType2["COMPLETE_BLOCK"] = "complete_block";
2250
+ ActionType2["ADD_BLOCK_TO_PLAYLIST"] = "add_to_playlist";
2251
+ return ActionType2;
2252
+ })(ActionType || {});
2253
+ var action_type_default = ActionType;
2254
+
2255
+ // src/server/utility/parse-index-path.ts
2256
+ var import_errors6 = __toESM(require_src2());
2257
+ function parseIndexPath(index_path) {
2258
+ if (index_path === void 0) {
2259
+ throw new import_errors6.InvariantViolation(`Undefined index path`);
2260
+ }
2261
+ if (index_path.trim() === "") {
2262
+ throw new import_errors6.InvariantViolation(`Invalid index path: ${index_path}`);
2263
+ }
2264
+ return index_path.split(".").map((part) => {
2265
+ const parsed_part = parseInt(part);
2266
+ if (isNaN(parsed_part)) {
2267
+ throw new import_errors6.InvariantViolation(`Invalid index path: ${index_path}`);
2268
+ }
2269
+ return parsed_part;
2270
+ });
2271
+ }
2272
+ var parse_index_path_default = parseIndexPath;
2273
+
2274
+ // src/server/utility/create-index-path.ts
2275
+ function createIndexPath(parts) {
2276
+ return parts.join(".");
2277
+ }
2278
+ var create_index_path_default = createIndexPath;
2279
+
2185
2280
  // src/client/utility/get-meta-value.ts
2186
- var import_errors5 = __toESM(require_src2());
2281
+ var import_errors7 = __toESM(require_src2());
2187
2282
  function getMetaValue(name) {
2188
2283
  const element = document.querySelector(`meta[name="${name}"]`);
2189
2284
  if (element === null) {
2190
- throw new import_errors5.InvariantViolation(`
2285
+ throw new import_errors7.InvariantViolation(`
2191
2286
  Tried to read ${name} meta tag, but it was not set
2192
2287
  `);
2193
2288
  }
2194
2289
  if (!(element instanceof HTMLMetaElement)) {
2195
- throw new import_errors5.InvariantViolation(`
2290
+ throw new import_errors7.InvariantViolation(`
2196
2291
  Got wrong element for ${name} meta tag: ${element.tagName}
2197
2292
  `);
2198
2293
  }
@@ -2201,11 +2296,23 @@
2201
2296
  }
2202
2297
  var get_meta_value_default = getMetaValue;
2203
2298
 
2299
+ // src/common/utility/increment-index-path.ts
2300
+ function incrementIndexPath(index_path) {
2301
+ const parsed_path = parse_index_path_default(index_path);
2302
+ const last_value = parsed_path.pop();
2303
+ if (last_value === void 0) {
2304
+ return "0";
2305
+ }
2306
+ parsed_path.push(last_value + 1);
2307
+ return create_index_path_default(parsed_path);
2308
+ }
2309
+ var increment_index_path_default = incrementIndexPath;
2310
+
2204
2311
  // src/server/utility/validate-path.ts
2205
- var import_errors6 = __toESM(require_src2());
2312
+ var import_errors8 = __toESM(require_src2());
2206
2313
  function validatePath(path) {
2207
2314
  if (!path.startsWith("/")) {
2208
- throw new import_errors6.InvalidError(`Invalid path: ${path}`);
2315
+ throw new import_errors8.InvalidError(`Invalid path: ${path}`);
2209
2316
  }
2210
2317
  }
2211
2318
  var validate_path_default = validatePath;
@@ -2244,31 +2351,37 @@
2244
2351
 
2245
2352
  // src/client/helper/interaction.ts
2246
2353
  var import_time = __toESM(require_src6());
2247
- var import_errors8 = __toESM(require_src2());
2354
+ var import_errors11 = __toESM(require_src2());
2248
2355
 
2249
- // src/enum/action-type.ts
2250
- var ActionType = /* @__PURE__ */ ((ActionType2) => {
2251
- ActionType2["ADD_BLOCK"] = "add_block";
2252
- ActionType2["DELETE_BLOCK"] = "delete_block";
2253
- ActionType2["MOVE_BLOCK"] = "move_block";
2254
- ActionType2["HIDE_BLOCK"] = "hide_block";
2255
- ActionType2["PROMOTE_BLOCK"] = "promote_block";
2256
- ActionType2["DEMOTE_BLOCK"] = "demote_block";
2257
- ActionType2["REPOSITION_BLOCK"] = "reposition_block";
2258
- ActionType2["EDIT_BLOCK"] = "edit_block";
2259
- ActionType2["CREATE_PAGE"] = "create_page";
2260
- ActionType2["COMPLETE_BLOCK"] = "complete_block";
2261
- ActionType2["ADD_BLOCK_TO_PLAYLIST"] = "add_to_playlist";
2262
- return ActionType2;
2263
- })(ActionType || {});
2264
- var action_type_default = ActionType;
2356
+ // src/client/utility/recompute-index-paths.ts
2357
+ var import_errors9 = __toESM(require_src2());
2358
+ function recomputeIndexPaths() {
2359
+ const raw_blocks = document.querySelectorAll("section.block");
2360
+ const blocks = Array.from(raw_blocks);
2361
+ let index = 0;
2362
+ blocks.forEach((block) => {
2363
+ const block_parent = block.parentNode;
2364
+ if (block_parent === null) {
2365
+ throw new import_errors9.InvariantViolation(`
2366
+ Tried to read block parent element, but it was not set
2367
+ `);
2368
+ }
2369
+ const multicolumn_ancestor = block_parent.closest("section.block.multi_column");
2370
+ if (multicolumn_ancestor === null) {
2371
+ const index_path = index.toString();
2372
+ block.setAttribute("data-index-path", index_path);
2373
+ index++;
2374
+ }
2375
+ });
2376
+ }
2377
+ var recompute_index_paths_default = recomputeIndexPaths;
2265
2378
 
2266
2379
  // src/client/utility/get-index-path-for-element.ts
2267
- var import_errors7 = __toESM(require_src2());
2380
+ var import_errors10 = __toESM(require_src2());
2268
2381
  function getIndexPathForElement(element) {
2269
2382
  const value = element.getAttribute("data-index-path");
2270
2383
  if (value === null) {
2271
- throw new import_errors7.InvariantViolation(
2384
+ throw new import_errors10.InvariantViolation(
2272
2385
  "Tried to read data-index-path for element, but it was not set"
2273
2386
  );
2274
2387
  }
@@ -2407,7 +2520,7 @@
2407
2520
  candidate.classList.remove("drag-candidate");
2408
2521
  const { parentNode } = candidate;
2409
2522
  if (parentNode === null) {
2410
- throw new import_errors8.InvariantViolation(`
2523
+ throw new import_errors11.InvariantViolation(`
2411
2524
  Expected drag candidate to be located in a parent, but it was null
2412
2525
  `);
2413
2526
  }
@@ -2456,13 +2569,13 @@
2456
2569
  const start_coordinate = this.getDragStartCoordinate();
2457
2570
  const current_coordinate = this.getDragCurrentCoordinate();
2458
2571
  if (start_coordinate === null) {
2459
- throw new import_errors8.InvariantViolation(`
2572
+ throw new import_errors11.InvariantViolation(`
2460
2573
  Tried to read start coordinate during touch event,
2461
2574
  but it was not set
2462
2575
  `);
2463
2576
  }
2464
2577
  if (current_coordinate === null) {
2465
- throw new import_errors8.InvariantViolation(`
2578
+ throw new import_errors11.InvariantViolation(`
2466
2579
  Tried to read current coordinate during touch event,
2467
2580
  but it was not set
2468
2581
  `);
@@ -2479,7 +2592,7 @@
2479
2592
  element.style.transform = `translateX(${normalized_delta}px)`;
2480
2593
  const nav = element.querySelector("nav");
2481
2594
  if (nav === null) {
2482
- throw new import_errors8.InvariantViolation(`
2595
+ throw new import_errors11.InvariantViolation(`
2483
2596
  Tried to read nav element for block, but it was not found
2484
2597
  `);
2485
2598
  }
@@ -2514,7 +2627,7 @@
2514
2627
  block.classList.remove("swiping");
2515
2628
  const nav = block.querySelector("nav");
2516
2629
  if (nav === null) {
2517
- throw new import_errors8.InvariantViolation(`
2630
+ throw new import_errors11.InvariantViolation(`
2518
2631
  Tried to read nav within swiping block, but it was not found
2519
2632
  `);
2520
2633
  }
@@ -2580,7 +2693,7 @@
2580
2693
  const x_attribute = block.getAttribute("data-drag-start-x");
2581
2694
  const y_attribute = block.getAttribute("data-drag-start-y");
2582
2695
  if (x_attribute === null || y_attribute === null) {
2583
- throw new import_errors8.InvariantViolation(`
2696
+ throw new import_errors11.InvariantViolation(`
2584
2697
  Drag coordinate attributes were invalid:
2585
2698
  x: ${x_attribute}
2586
2699
  y: ${y_attribute}
@@ -2589,7 +2702,7 @@
2589
2702
  const parsed_x = parseInt(x_attribute);
2590
2703
  const parsed_y = parseInt(y_attribute);
2591
2704
  if (isNaN(parsed_x) || isNaN(parsed_y)) {
2592
- throw new import_errors8.InvariantViolation(`
2705
+ throw new import_errors11.InvariantViolation(`
2593
2706
  Drag coordinate attributes were invalid:
2594
2707
  x: ${x_attribute}
2595
2708
  y: ${y_attribute}
@@ -2602,7 +2715,7 @@
2602
2715
  const y_delta = current_y - start_y;
2603
2716
  const container = document.querySelector("main");
2604
2717
  if (container === null) {
2605
- throw new import_errors8.InvariantViolation(`
2718
+ throw new import_errors11.InvariantViolation(`
2606
2719
  Unable to find <main> container element in the DOM
2607
2720
  `);
2608
2721
  }
@@ -2684,7 +2797,7 @@
2684
2797
  }
2685
2798
  getLastScrollTime() {
2686
2799
  if (this.last_scroll_time === null) {
2687
- throw new import_errors8.InvariantViolation(`
2800
+ throw new import_errors11.InvariantViolation(`
2688
2801
  Tried to read last scroll time, but it was not set
2689
2802
  `);
2690
2803
  }
@@ -2735,7 +2848,7 @@
2735
2848
  const index_path = get_index_path_for_element_default(block);
2736
2849
  const ghost = document.querySelector(`[data-for="${index_path}"]`);
2737
2850
  if (ghost === null) {
2738
- throw new import_errors8.InvariantViolation(`
2851
+ throw new import_errors11.InvariantViolation(`
2739
2852
  Unable to find ghost for block with index path ${index_path}
2740
2853
  `);
2741
2854
  }
@@ -2747,7 +2860,7 @@
2747
2860
  const ghost = this.getGhostForBlock(block);
2748
2861
  let index = siblings.indexOf(ghost);
2749
2862
  if (index === -1) {
2750
- throw new import_errors8.InvariantViolation("Unable to locate ghost within siblings");
2863
+ throw new import_errors11.InvariantViolation("Unable to locate ghost within siblings");
2751
2864
  }
2752
2865
  while (index--) {
2753
2866
  const sibling = siblings[index];
@@ -2771,7 +2884,7 @@
2771
2884
  const ghost = this.getGhostForBlock(block);
2772
2885
  let index = siblings.indexOf(ghost);
2773
2886
  if (index === -1) {
2774
- throw new import_errors8.InvariantViolation("Unable to locate ghost within siblings");
2887
+ throw new import_errors11.InvariantViolation("Unable to locate ghost within siblings");
2775
2888
  }
2776
2889
  index++;
2777
2890
  while (index < siblings.length) {
@@ -2848,32 +2961,13 @@
2848
2961
  element.classList.remove("dragging");
2849
2962
  ghost.replaceWith(element);
2850
2963
  element.style.opacity = "1";
2964
+ recompute_index_paths_default();
2851
2965
  }
2852
- this.recomputeIndexPaths();
2853
- }
2854
- recomputeIndexPaths() {
2855
- const raw_blocks = document.querySelectorAll("section.block");
2856
- const blocks = Array.from(raw_blocks);
2857
- let index = 0;
2858
- blocks.forEach((block) => {
2859
- const block_parent = block.parentNode;
2860
- if (block_parent === null) {
2861
- throw new import_errors8.InvariantViolation(`
2862
- Tried to read block parent element, but it was not set
2863
- `);
2864
- }
2865
- const multicolumn_ancestor = block_parent.closest("section.block.multi_column");
2866
- if (multicolumn_ancestor === null) {
2867
- const index_path = index.toString();
2868
- block.setAttribute("data-index-path", index_path);
2869
- index++;
2870
- }
2871
- });
2872
2966
  }
2873
2967
  getIndexPathForGhost(ghost) {
2874
2968
  const parent_element = ghost.parentNode;
2875
2969
  if (parent_element === null) {
2876
- throw new import_errors8.InvariantViolation(`
2970
+ throw new import_errors11.InvariantViolation(`
2877
2971
  Tried to read parent element for ghost, but it was not set
2878
2972
  `);
2879
2973
  }
@@ -2901,18 +2995,12 @@
2901
2995
  form.set("action_type", action_type_default.REPOSITION_BLOCK);
2902
2996
  form.set("source_index_path", source_index_path);
2903
2997
  form.set("target_index_path", target_index_path);
2904
- const response = await fetch(`/actions`, {
2998
+ await fetch(`/actions`, {
2905
2999
  method: "POST",
2906
3000
  body: form,
2907
3001
  credentials: "same-origin",
2908
3002
  redirect: "follow"
2909
3003
  });
2910
- try {
2911
- const url_object = new URL(response.url, window.location.origin);
2912
- return url_object.searchParams.get("index_path");
2913
- } catch (_) {
2914
- return null;
2915
- }
2916
3004
  }
2917
3005
  getEventCoordinate(event) {
2918
3006
  const { touches } = event;
@@ -2942,7 +3030,7 @@
2942
3030
  }
2943
3031
  getCurrentScrollY() {
2944
3032
  if (this.current_scroll_y === null) {
2945
- throw new import_errors8.InvariantViolation(`
3033
+ throw new import_errors11.InvariantViolation(`
2946
3034
  Tried to read current scroll y, but it was not set
2947
3035
  `);
2948
3036
  }
@@ -3034,7 +3122,7 @@
3034
3122
  if (activator !== null) {
3035
3123
  const block = activator.closest("section.block");
3036
3124
  if (block === null) {
3037
- throw new import_errors9.InvariantViolation(`
3125
+ throw new import_errors12.InvariantViolation(`
3038
3126
  Unable to handle activator; no wrapping block was found
3039
3127
  `);
3040
3128
  }
@@ -3071,6 +3159,9 @@
3071
3159
  return;
3072
3160
  }
3073
3161
  const html = await response.text();
3162
+ this.injectHtml(html, path);
3163
+ }
3164
+ injectHtml(html, fallback_path) {
3074
3165
  const parser = new DOMParser();
3075
3166
  const updated_document = parser.parseFromString(html, "text/html");
3076
3167
  const tags = ["header", "main", "footer"];
@@ -3083,7 +3174,7 @@
3083
3174
  continue;
3084
3175
  }
3085
3176
  if (old_element === null || new_element === null) {
3086
- window.location.href = path;
3177
+ window.location.href = fallback_path;
3087
3178
  return;
3088
3179
  }
3089
3180
  old_element.replaceWith(new_element);
@@ -3136,13 +3227,13 @@
3136
3227
  const link_id = `${block_id}-add-to-playlist`;
3137
3228
  const link_element = document.getElementById(link_id);
3138
3229
  if (link_element === null) {
3139
- throw new import_errors9.InvariantViolation(`
3230
+ throw new import_errors12.InvariantViolation(`
3140
3231
  Unable to find playlist link element for block: ${block_id}
3141
3232
  `);
3142
3233
  }
3143
3234
  const href = link_element.getAttribute("href");
3144
3235
  if (href === null) {
3145
- throw new import_errors9.InvariantViolation(`
3236
+ throw new import_errors12.InvariantViolation(`
3146
3237
  Unable to find playlist link href for block: ${block_id}
3147
3238
  `);
3148
3239
  }
@@ -3162,37 +3253,72 @@
3162
3253
  if (!this.isLoggedIn()) {
3163
3254
  return;
3164
3255
  }
3165
- const block_element = this.getCurrentBlockElement();
3166
- if (block_element === null) {
3256
+ const source_index_path = this.getCurrentBlockIndex();
3257
+ const target_index_path = this.getPreviousBlockIndex();
3258
+ if (target_index_path === null) {
3167
3259
  return;
3168
3260
  }
3169
- const block_id = block_element.id;
3170
- const form_id = `${block_id}-promote`;
3171
- const form_element = document.getElementById(form_id);
3172
- if (form_element === null) {
3173
- throw new import_errors9.InvariantViolation(`
3174
- Unable to find promotion form element for block: ${block_id}
3175
- `);
3261
+ const parsed_source = parse_index_path_default(source_index_path);
3262
+ const parsed_target = parse_index_path_default(target_index_path);
3263
+ if (parsed_target.length > parsed_source.length) {
3264
+ const new_last_sibling_index_path = increment_index_path_default(target_index_path);
3265
+ this.submitReposition(source_index_path, new_last_sibling_index_path);
3266
+ } else {
3267
+ this.submitReposition(source_index_path, target_index_path);
3176
3268
  }
3177
- form_element.submit();
3178
3269
  }
3179
3270
  demoteCurrentBlock() {
3180
3271
  if (!this.isLoggedIn()) {
3181
3272
  return;
3182
3273
  }
3183
- const block_element = this.getCurrentBlockElement();
3184
- if (block_element === null) {
3274
+ const source_index_path = this.getCurrentBlockIndex();
3275
+ const target_index_path = this.getNextBlockIndex();
3276
+ if (target_index_path === null) {
3185
3277
  return;
3186
3278
  }
3187
- const block_id = block_element.id;
3188
- const form_id = `${block_id}-demote`;
3189
- const form_element = document.getElementById(form_id);
3190
- if (form_element === null) {
3191
- throw new import_errors9.InvariantViolation(`
3192
- Unable to find demotion form element for block: ${block_id}
3279
+ const next_block = this.getBlockElementForIndexPath(target_index_path);
3280
+ if (next_block === null) {
3281
+ throw new import_errors12.InvariantViolation(`
3282
+ Tried to read next block, but it was not set
3193
3283
  `);
3194
3284
  }
3195
- form_element.submit();
3285
+ const attribute = next_block.getAttribute("data-block-type");
3286
+ if (attribute === null) {
3287
+ throw new import_errors12.InvariantViolation(`
3288
+ Tried to read block type attribute from next block, but it was not set
3289
+ `);
3290
+ }
3291
+ const block_type = attribute;
3292
+ if (block_type !== block_type_default.MULTI_COLUMN) {
3293
+ this.submitReposition(source_index_path, target_index_path);
3294
+ return;
3295
+ }
3296
+ const parsed_path = parse_index_path_default(target_index_path);
3297
+ parsed_path.push(0);
3298
+ const new_first_child_path = create_index_path_default(parsed_path);
3299
+ this.submitReposition(source_index_path, new_first_child_path);
3300
+ }
3301
+ async submitReposition(source_index_path, target_index_path) {
3302
+ const form = new FormData();
3303
+ form.set("path", window.location.pathname);
3304
+ form.set("action_type", action_type_default.REPOSITION_BLOCK);
3305
+ form.set("source_index_path", source_index_path);
3306
+ form.set("target_index_path", target_index_path);
3307
+ const response = await fetch(`/actions`, {
3308
+ method: "POST",
3309
+ body: form,
3310
+ credentials: "same-origin",
3311
+ redirect: "follow",
3312
+ headers: {
3313
+ "Accept": "text/html"
3314
+ }
3315
+ });
3316
+ const html = await response.text();
3317
+ const url = new URL(response.url);
3318
+ url.searchParams.delete("toast_message");
3319
+ url.searchParams.delete("toast_color");
3320
+ history.replaceState({}, "", url);
3321
+ this.injectHtml(html, response.url);
3196
3322
  }
3197
3323
  performPageJump() {
3198
3324
  if (!this.shiftIsPressed()) {
@@ -3235,7 +3361,7 @@
3235
3361
  }
3236
3362
  });
3237
3363
  if (!found) {
3238
- throw new import_errors9.InvariantViolation(`
3364
+ throw new import_errors12.InvariantViolation(`
3239
3365
  Tried to navigate to element at index path ${index_path},
3240
3366
  but matching element was not found
3241
3367
  `);
@@ -3271,11 +3397,12 @@
3271
3397
  }
3272
3398
  }
3273
3399
  getCurrentBlockIndex() {
3274
- const element = this.getCurrentBlockElement();
3275
- if (element === null) {
3276
- return "0";
3400
+ const query_path = this.getQueryParameter("index_path");
3401
+ if (query_path !== void 0) {
3402
+ return query_path;
3277
3403
  }
3278
- return get_index_path_for_element_default(element);
3404
+ const first_block_index = this.getFirstBlockIndex();
3405
+ return first_block_index || "0";
3279
3406
  }
3280
3407
  getCurrentBlockNumericIndex() {
3281
3408
  const index = this.getCurrentBlockIndex();
@@ -3286,23 +3413,14 @@
3286
3413
  return Array.from(elements);
3287
3414
  }
3288
3415
  getCurrentBlockElement() {
3289
- const block_elements = this.getBlockElements();
3290
- const selected_element = block_elements.find((element2) => {
3291
- return element2.classList.contains("selected");
3292
- });
3293
- if (selected_element !== void 0) {
3294
- return selected_element;
3295
- }
3296
- const index_path = (() => {
3297
- const query_path = this.getQueryParameter("index_path");
3298
- if (query_path !== void 0) {
3299
- return query_path;
3300
- }
3301
- return this.getFirstBlockIndex();
3302
- })();
3416
+ const index_path = this.getCurrentBlockIndex();
3303
3417
  if (index_path === null) {
3304
3418
  return null;
3305
3419
  }
3420
+ return this.getBlockElementForIndexPath(index_path);
3421
+ }
3422
+ getBlockElementForIndexPath(index_path) {
3423
+ const block_elements = this.getBlockElements();
3306
3424
  const element = block_elements.find((element2) => {
3307
3425
  const attribute = get_index_path_for_element_default(element2);
3308
3426
  return attribute === index_path;
@@ -3354,14 +3472,14 @@
3354
3472
  activateBlock(block_element) {
3355
3473
  const attribute = block_element.getAttribute("data-block-type");
3356
3474
  if (attribute === null) {
3357
- throw new import_errors9.InvariantViolation(`
3475
+ throw new import_errors12.InvariantViolation(`
3358
3476
  Tried to activate current block, but it did not have a block type
3359
3477
  `);
3360
3478
  }
3361
3479
  const block_type = attribute;
3362
3480
  const block_types = Object.values(block_type_default);
3363
3481
  if (!block_types.includes(block_type)) {
3364
- throw new import_errors9.InvariantViolation(`
3482
+ throw new import_errors12.InvariantViolation(`
3365
3483
  Invalid block type: ${block_type}
3366
3484
  `);
3367
3485
  }
@@ -3382,7 +3500,7 @@
3382
3500
  const forms = block_element.getElementsByTagName("form");
3383
3501
  const form = forms[0];
3384
3502
  if (form === void 0) {
3385
- throw new import_errors9.InvariantViolation(`
3503
+ throw new import_errors12.InvariantViolation(`
3386
3504
  Tried to activate form for todo block, but it was not set
3387
3505
  `);
3388
3506
  }
@@ -3399,7 +3517,7 @@
3399
3517
  activateAudioBlock(block_element) {
3400
3518
  const audio_element = block_element.querySelector("audio");
3401
3519
  if (audio_element === null) {
3402
- throw new import_errors9.InvariantViolation(`
3520
+ throw new import_errors12.InvariantViolation(`
3403
3521
  Tried to read audio element for block, but it was not present
3404
3522
  `);
3405
3523
  }
@@ -3428,7 +3546,7 @@
3428
3546
  this.pauseActiveMedia();
3429
3547
  const media_block = element.closest("section.block");
3430
3548
  if (media_block === null) {
3431
- throw new import_errors9.InvariantViolation(`
3549
+ throw new import_errors12.InvariantViolation(`
3432
3550
  Tried to access closest block wrapper for media, but it was not found
3433
3551
  `);
3434
3552
  }
@@ -3438,7 +3556,7 @@
3438
3556
  const persistent_element = document.getElementById("persistent-audio");
3439
3557
  const persistent_audio = persistent_element;
3440
3558
  if (persistent_audio === null) {
3441
- throw new import_errors9.InvariantViolation(`
3559
+ throw new import_errors12.InvariantViolation(`
3442
3560
  Tried to access persistent audio element, but it was not found
3443
3561
  `);
3444
3562
  }
@@ -3451,22 +3569,22 @@
3451
3569
  const track_source = media_block.querySelector('[data-role="track_name"]');
3452
3570
  const artist_source = media_block.querySelector('[data-role="artist_name"]');
3453
3571
  if (track_target === null) {
3454
- throw new import_errors9.InvariantViolation(`
3572
+ throw new import_errors12.InvariantViolation(`
3455
3573
  Tried to access persistent track name element, but it was not found
3456
3574
  `);
3457
3575
  }
3458
3576
  if (artist_target === null) {
3459
- throw new import_errors9.InvariantViolation(`
3577
+ throw new import_errors12.InvariantViolation(`
3460
3578
  Tried to access persistent artist name element, but it was not found
3461
3579
  `);
3462
3580
  }
3463
3581
  if (track_source === null) {
3464
- throw new import_errors9.InvariantViolation(`
3582
+ throw new import_errors12.InvariantViolation(`
3465
3583
  Tried to read track name source, but it was not found
3466
3584
  `);
3467
3585
  }
3468
3586
  if (artist_source === null) {
3469
- throw new import_errors9.InvariantViolation(`
3587
+ throw new import_errors12.InvariantViolation(`
3470
3588
  Tried to read artist name source, but it was not found
3471
3589
  `);
3472
3590
  }
@@ -3528,7 +3646,7 @@
3528
3646
  if (block !== null) {
3529
3647
  const duration_label = block.querySelector('[data-role="duration"]');
3530
3648
  if (duration_label === null) {
3531
- throw new import_errors9.InvariantViolation(`
3649
+ throw new import_errors12.InvariantViolation(`
3532
3650
  Tried to read duration label for media block, but it was not found
3533
3651
  `);
3534
3652
  }
@@ -3632,12 +3750,148 @@
3632
3750
  var select_block_destination_default = SelectBlockDestinationPage;
3633
3751
 
3634
3752
  // src/client/page/edit-block.ts
3635
- var import_errors10 = __toESM(require_src2());
3753
+ var import_errors13 = __toESM(require_src2());
3754
+ var import_time3 = __toESM(require_src6());
3636
3755
  var EditBlockPage = class extends page_default {
3756
+ constructor() {
3757
+ super();
3758
+ this.last_preview_time = Date.now();
3759
+ }
3637
3760
  initEvents() {
3638
3761
  super.initEvents();
3762
+ this.initNumericRangeInputEvents();
3639
3763
  this.initFileInputEvents();
3640
3764
  this.initTextareaEvents();
3765
+ this.initTextInputEvents();
3766
+ }
3767
+ initNumericRangeInputEvents() {
3768
+ const input_nodes = document.querySelectorAll('input[type="range"]');
3769
+ const inputs = Array.from(input_nodes);
3770
+ inputs.forEach((input) => {
3771
+ const handler = () => {
3772
+ const value = input.value;
3773
+ const container = input.closest('[data-role="numeric-range-container"]');
3774
+ if (container === null) {
3775
+ throw new import_errors13.InvariantViolation(`
3776
+ Unable to find numeric range container for range input
3777
+ `);
3778
+ }
3779
+ const raw_labels = container.querySelectorAll('[data-role="numeric-range-value"]');
3780
+ const labels = Array.from(raw_labels);
3781
+ labels.forEach((label) => {
3782
+ label.innerHTML = value;
3783
+ });
3784
+ };
3785
+ input.addEventListener("change", () => {
3786
+ handler();
3787
+ this.loadPreview();
3788
+ });
3789
+ input.addEventListener("input", () => {
3790
+ handler();
3791
+ this.queuePreview();
3792
+ });
3793
+ });
3794
+ ;
3795
+ }
3796
+ async loadPreview() {
3797
+ this.last_preview_time = Date.now();
3798
+ this.clearPreviewTimer();
3799
+ const form = new FormData();
3800
+ const block_type = this.getPreviewInputValue("block_type");
3801
+ const color = this.getPreviewRadioValue("color");
3802
+ const index_path = this.getPreviewInputValue("index_path");
3803
+ const border_width = this.getPreviewInputValue("border_width");
3804
+ const create_role = this.getPreviewInputValue("create_role");
3805
+ const read_role = this.getPreviewInputValue("read_role");
3806
+ const update_role = this.getPreviewInputValue("update_role");
3807
+ const delete_role = this.getPreviewInputValue("delete_role");
3808
+ const visibility = this.getPreviewRadioValue("time_place_visibility");
3809
+ form.set("path", window.location.pathname);
3810
+ form.set("action_type", action_type_default.PREVIEW_BLOCK);
3811
+ form.set("color", color);
3812
+ form.set("block_type", block_type);
3813
+ form.set("index_path", index_path);
3814
+ form.set("border_width", border_width);
3815
+ form.set("create_role", create_role);
3816
+ form.set("read_role", read_role);
3817
+ form.set("update_role", update_role);
3818
+ form.set("delete_role", delete_role);
3819
+ form.set("time_place_visibility", visibility);
3820
+ if (block_type === block_type_default.NOTE) {
3821
+ const text = this.getPreviewInputValue("text");
3822
+ form.set("text", text);
3823
+ }
3824
+ if (block_type === block_type_default.TODO) {
3825
+ const title = this.getPreviewInputValue("title");
3826
+ form.set("title", title);
3827
+ }
3828
+ if (block_type === block_type_default.LINK) {
3829
+ const href = this.getPreviewInputValue("href");
3830
+ const label = this.getPreviewInputValue("label");
3831
+ form.set("href", href);
3832
+ form.set("label", label);
3833
+ }
3834
+ if (block_type === block_type_default.FOLDER) {
3835
+ const title = this.getPreviewInputValue("title");
3836
+ const emoji = this.getPreviewInputValue("emoji");
3837
+ const subtitle = this.getPreviewInputValue("subtitle");
3838
+ form.set("title", title);
3839
+ form.set("emoji", emoji);
3840
+ form.set("subtitle", subtitle);
3841
+ }
3842
+ if (block_type === block_type_default.HEADER) {
3843
+ const title = this.getPreviewInputValue("title");
3844
+ const emoji = this.getPreviewInputValue("emoji");
3845
+ const size = this.getPreviewRadioValue("size");
3846
+ form.set("title", title);
3847
+ form.set("emoji", emoji);
3848
+ form.set("size", size);
3849
+ }
3850
+ if (block_type === block_type_default.INPUT) {
3851
+ const parameter_name = this.getPreviewInputValue("parameter_name");
3852
+ form.set("parameter_name", parameter_name);
3853
+ }
3854
+ if (block_type === block_type_default.BUTTON) {
3855
+ const label = this.getPreviewInputValue("label");
3856
+ form.set("label", label);
3857
+ }
3858
+ const response = await fetch(`/actions`, {
3859
+ method: "POST",
3860
+ body: form,
3861
+ credentials: "same-origin",
3862
+ redirect: "follow"
3863
+ });
3864
+ const html = await response.text();
3865
+ const parser = new DOMParser();
3866
+ const old_element = document.querySelector('[data-role="preview_wrapper"]');
3867
+ const fragment = parser.parseFromString(html, "text/html");
3868
+ const new_element = fragment.querySelector("section");
3869
+ if (old_element === null) {
3870
+ throw new import_errors13.InvariantViolation(`
3871
+ Unable to find current preview wrapper element
3872
+ `);
3873
+ }
3874
+ if (new_element === null) {
3875
+ throw new import_errors13.InvariantViolation(`
3876
+ Unable to find <section> element on block preview HTML response
3877
+ `);
3878
+ }
3879
+ old_element.replaceWith(new_element);
3880
+ new_element.setAttribute("data-role", "preview_wrapper");
3881
+ }
3882
+ clearPreviewTimer() {
3883
+ if (this.preview_timer !== void 0) {
3884
+ clearTimeout(this.preview_timer);
3885
+ }
3886
+ }
3887
+ queuePreview() {
3888
+ this.clearPreviewTimer();
3889
+ const time_since_last_preview = Date.now() - this.last_preview_time;
3890
+ const max_delay = import_time3.TimeInterval.ONE_SECOND / 2;
3891
+ const delay = max_delay - time_since_last_preview;
3892
+ this.preview_timer = setTimeout(() => {
3893
+ this.loadPreview();
3894
+ }, delay);
3641
3895
  }
3642
3896
  initFileInputEvents() {
3643
3897
  const input_nodes = document.querySelectorAll('input[type="file"]');
@@ -3653,7 +3907,7 @@
3653
3907
  });
3654
3908
  const label = input.nextElementSibling;
3655
3909
  if (label === null || !label.matches("label.biglink")) {
3656
- throw new import_errors10.InvariantViolation(`
3910
+ throw new import_errors13.InvariantViolation(`
3657
3911
  Tried to handle file change event,
3658
3912
  but no adjacent label element was found
3659
3913
  `);
@@ -3666,16 +3920,24 @@
3666
3920
  });
3667
3921
  });
3668
3922
  }
3923
+ initTextInputEvents() {
3924
+ const form = this.getEditForm();
3925
+ const input_nodes = form.querySelectorAll("input,textarea");
3926
+ const inputs = Array.from(input_nodes);
3927
+ inputs.forEach((input) => {
3928
+ input.addEventListener("change", () => {
3929
+ this.loadPreview();
3930
+ });
3931
+ input.addEventListener("input", () => {
3932
+ this.queuePreview();
3933
+ });
3934
+ });
3935
+ }
3669
3936
  initTextareaEvents() {
3670
- const textarea_nodes = document.querySelectorAll("textarea");
3937
+ const form = this.getEditForm();
3938
+ const textarea_nodes = form.querySelectorAll("textarea");
3671
3939
  const textareas = Array.from(textarea_nodes);
3672
3940
  textareas.forEach((textarea) => {
3673
- const form = textarea.closest("form");
3674
- if (form === null) {
3675
- throw new import_errors10.InvariantViolation(`
3676
- Tried to read form for textarea, but it was not set
3677
- `);
3678
- }
3679
3941
  textarea.addEventListener("keydown", (event) => {
3680
3942
  const key_code = event.keyCode || event.charCode;
3681
3943
  if (key_code === key_code_default.ENTER && event.shiftKey) {
@@ -3685,6 +3947,45 @@
3685
3947
  });
3686
3948
  });
3687
3949
  }
3950
+ getEditForm() {
3951
+ const form = document.querySelector('form[data-role="edit_block"]');
3952
+ if (form === null) {
3953
+ throw new import_errors13.InvariantViolation(`
3954
+ Tried to read edit block form, but it was not found
3955
+ `);
3956
+ }
3957
+ return form;
3958
+ }
3959
+ getPreviewRadioValue(input_name) {
3960
+ const edit_form = this.getEditForm();
3961
+ const input_element = edit_form.querySelector(`[name="${input_name}"]:checked`);
3962
+ if (input_element === null) {
3963
+ throw new import_errors13.InvariantViolation(`
3964
+ Tried to read radio value for input named "${input_name}",
3965
+ but it was not found
3966
+ `);
3967
+ }
3968
+ const input = input_element;
3969
+ return input.value;
3970
+ }
3971
+ getPreviewInputValue(input_name) {
3972
+ const edit_form = this.getEditForm();
3973
+ const input_element = edit_form.querySelector(`[name="${input_name}"]`);
3974
+ if (input_element === null) {
3975
+ throw new import_errors13.InvariantViolation(`
3976
+ Tried to read input value for input named "${input_name}",
3977
+ but it was not found
3978
+ `);
3979
+ }
3980
+ const input = input_element;
3981
+ const input_type = input.getAttribute("type");
3982
+ if (input_type === "radio") {
3983
+ throw new import_errors13.InvariantViolation(`
3984
+ You must use .getPreviewRadioValue() for dealing with radio inputs
3985
+ `);
3986
+ }
3987
+ return input.value;
3988
+ }
3688
3989
  };
3689
3990
  var edit_block_default = EditBlockPage;
3690
3991
 
@@ -3694,7 +3995,7 @@
3694
3995
  var create_block_default = CreateBlockPage;
3695
3996
 
3696
3997
  // src/client/page/view-custom.ts
3697
- var import_errors11 = __toESM(require_src2());
3998
+ var import_errors14 = __toESM(require_src2());
3698
3999
  var ViewCustomPage = class extends cursor_default {
3699
4000
  handleKey(key_code) {
3700
4001
  switch (key_code) {
@@ -3724,13 +4025,13 @@
3724
4025
  const link_id = `${block_id}-edit`;
3725
4026
  const link_element = document.getElementById(link_id);
3726
4027
  if (link_element === null) {
3727
- throw new import_errors11.InvariantViolation(`
4028
+ throw new import_errors14.InvariantViolation(`
3728
4029
  Unable to find edit link element for block: ${block_id}
3729
4030
  `);
3730
4031
  }
3731
4032
  const href = link_element.getAttribute("href");
3732
4033
  if (href === null) {
3733
- throw new import_errors11.InvariantViolation(`
4034
+ throw new import_errors14.InvariantViolation(`
3734
4035
  Unable to find edit link href for block: ${block_id}
3735
4036
  `);
3736
4037
  }
@@ -3743,7 +4044,7 @@
3743
4044
  const current_path = this.getCurrentBlockIndex();
3744
4045
  const top_level_index = parseInt(current_path, 10);
3745
4046
  if (isNaN(top_level_index)) {
3746
- throw new import_errors11.InvariantViolation(`Invalid index path: ${current_path}`);
4047
+ throw new import_errors14.InvariantViolation(`Invalid index path: ${current_path}`);
3747
4048
  }
3748
4049
  const add_block_links = document.querySelectorAll('[data-role="add_block_link"]');
3749
4050
  const link_index = (() => {
@@ -3755,14 +4056,14 @@
3755
4056
  })();
3756
4057
  const link = add_block_links[link_index];
3757
4058
  if (link === void 0) {
3758
- throw new import_errors11.InvariantViolation(`
4059
+ throw new import_errors14.InvariantViolation(`
3759
4060
  Tried to read link at index ${link_index},
3760
4061
  but it was not found
3761
4062
  `);
3762
4063
  }
3763
4064
  const href = link.getAttribute("href");
3764
4065
  if (href === null) {
3765
- throw new import_errors11.InvariantViolation(`
4066
+ throw new import_errors14.InvariantViolation(`
3766
4067
  Tried to read href for link at index ${link_index},
3767
4068
  but it was not set
3768
4069
  `);
@@ -3781,13 +4082,13 @@
3781
4082
  const link_id = `${block_id}-move`;
3782
4083
  const link_element = document.getElementById(link_id);
3783
4084
  if (link_element === null) {
3784
- throw new import_errors11.InvariantViolation(`
4085
+ throw new import_errors14.InvariantViolation(`
3785
4086
  Unable to find move link element for block: ${block_id}
3786
4087
  `);
3787
4088
  }
3788
4089
  const href = link_element.getAttribute("href");
3789
4090
  if (href === null) {
3790
- throw new import_errors11.InvariantViolation(`
4091
+ throw new import_errors14.InvariantViolation(`
3791
4092
  Unable to find move link href for block: ${block_id}
3792
4093
  `);
3793
4094
  }
@@ -3808,13 +4109,13 @@
3808
4109
  const link_id = `${block_id}-hide`;
3809
4110
  const link_element = document.getElementById(link_id);
3810
4111
  if (link_element === null) {
3811
- throw new import_errors11.InvariantViolation(`
4112
+ throw new import_errors14.InvariantViolation(`
3812
4113
  Unable to find hide link element for block: ${block_id}
3813
4114
  `);
3814
4115
  }
3815
4116
  const href = link_element.getAttribute("href");
3816
4117
  if (href === null) {
3817
- throw new import_errors11.InvariantViolation(`
4118
+ throw new import_errors14.InvariantViolation(`
3818
4119
  Unable to find hide link href for block: ${block_id}
3819
4120
  `);
3820
4121
  }
@@ -3825,13 +4126,13 @@
3825
4126
  const link_id = `${block_id}-delete`;
3826
4127
  const link_element = document.getElementById(link_id);
3827
4128
  if (link_element === null) {
3828
- throw new import_errors11.InvariantViolation(`
4129
+ throw new import_errors14.InvariantViolation(`
3829
4130
  Unable to find deletion link element for block: ${block_id}
3830
4131
  `);
3831
4132
  }
3832
4133
  const href = link_element.getAttribute("href");
3833
4134
  if (href === null) {
3834
- throw new import_errors11.InvariantViolation(`
4135
+ throw new import_errors14.InvariantViolation(`
3835
4136
  Unable to find deletion link href for block: ${block_id}
3836
4137
  `);
3837
4138
  }
@@ -3860,7 +4161,7 @@
3860
4161
  var edit_custom_default = EditCustomPage;
3861
4162
 
3862
4163
  // src/client/page/confirm-delete-block.ts
3863
- var import_errors12 = __toESM(require_src2());
4164
+ var import_errors15 = __toESM(require_src2());
3864
4165
  var ConfirmDeleteBlockPage = class extends page_default {
3865
4166
  handleKey(key_code) {
3866
4167
  switch (key_code) {
@@ -3873,7 +4174,7 @@
3873
4174
  submitDeletionForm() {
3874
4175
  const element = document.getElementById("deletion-form");
3875
4176
  if (element === null) {
3876
- throw new import_errors12.InvariantViolation("Could not find deletion form element");
4177
+ throw new import_errors15.InvariantViolation("Could not find deletion form element");
3877
4178
  }
3878
4179
  const form = element;
3879
4180
  form.submit();
@@ -3882,7 +4183,7 @@
3882
4183
  var confirm_delete_block_default = ConfirmDeleteBlockPage;
3883
4184
 
3884
4185
  // src/client/page/confirm-hide-block.ts
3885
- var import_errors13 = __toESM(require_src2());
4186
+ var import_errors16 = __toESM(require_src2());
3886
4187
  var ConfirmHideBlockPage = class extends page_default {
3887
4188
  handleKey(key_code) {
3888
4189
  switch (key_code) {
@@ -3895,7 +4196,7 @@
3895
4196
  submitHideForm() {
3896
4197
  const element = document.getElementById("hide-form");
3897
4198
  if (element === null) {
3898
- throw new import_errors13.InvariantViolation("Could not find hide form element");
4199
+ throw new import_errors16.InvariantViolation("Could not find hide form element");
3899
4200
  }
3900
4201
  const form = element;
3901
4202
  form.submit();
@@ -3988,7 +4289,7 @@
3988
4289
  const page_type = meta_value;
3989
4290
  const page_types = Object.values(page_type_default);
3990
4291
  if (!page_types.includes(page_type)) {
3991
- throw new import_errors14.InvariantViolation(`
4292
+ throw new import_errors17.InvariantViolation(`
3992
4293
  Invalid page type: ${page_type}
3993
4294
  `);
3994
4295
  }