@adminide-stack/yantra-mobile 12.0.140 → 12.0.141

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 (213) hide show
  1. package/lib/features/agent-chat/NativeAgentChat.js +21 -4
  2. package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
  3. package/lib/features/chat/ApprovalCard.js +353 -0
  4. package/lib/features/chat/ApprovalCard.js.map +1 -0
  5. package/lib/features/chat/AskUserCard.js +9 -2
  6. package/lib/features/chat/AskUserCard.js.map +1 -1
  7. package/lib/features/chat/askUser.js +25 -3
  8. package/lib/features/chat/askUser.js.map +1 -1
  9. package/lib/features/chat/queuedFollowUpRows.js +13 -0
  10. package/lib/features/chat/queuedFollowUpRows.js.map +1 -0
  11. package/lib/features/discover/DiscoverArticle.js +105 -92
  12. package/lib/features/discover/DiscoverArticle.js.map +1 -1
  13. package/lib/features/discover/DiscoverFeed.js +97 -48
  14. package/lib/features/discover/DiscoverFeed.js.map +1 -1
  15. package/lib/features/discover/DiscoverFollowUp.js +135 -0
  16. package/lib/features/discover/DiscoverFollowUp.js.map +1 -0
  17. package/lib/features/discover/DiscoverSidebar.js +555 -0
  18. package/lib/features/discover/DiscoverSidebar.js.map +1 -0
  19. package/lib/features/discover/DiscoverSkeletons.js +123 -0
  20. package/lib/features/discover/DiscoverSkeletons.js.map +1 -0
  21. package/lib/features/discover/DiscoverStoryCards.js +193 -87
  22. package/lib/features/discover/DiscoverStoryCards.js.map +1 -1
  23. package/lib/features/discover/followUpQuery.js +42 -0
  24. package/lib/features/discover/followUpQuery.js.map +1 -0
  25. package/lib/features/discover/markets.js +37 -0
  26. package/lib/features/discover/markets.js.map +1 -0
  27. package/lib/features/discover/useDiscoverSidebar.js +148 -0
  28. package/lib/features/discover/useDiscoverSidebar.js.map +1 -0
  29. package/lib/features/discover/weather.js +42 -0
  30. package/lib/features/discover/weather.js.map +1 -0
  31. package/lib/features/expenses/ExpensesAgentChatPane.js +1 -1
  32. package/lib/features/expenses/ExpensesAgentChatPane.js.map +1 -1
  33. package/lib/features/inbox/InboxAgentChatPane.js +1 -1
  34. package/lib/features/inbox/InboxAgentChatPane.js.map +1 -1
  35. package/lib/features/job-search/JobSearchAgentChatPane.js +1 -0
  36. package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -1
  37. package/lib/features/local-services/LocalServicesAgentChatPane.js +1 -1
  38. package/lib/features/local-services/LocalServicesAgentChatPane.js.map +1 -1
  39. package/lib/features/movies/MoviesAgentChatPane.js +1 -1
  40. package/lib/features/movies/MoviesAgentChatPane.js.map +1 -1
  41. package/lib/features/notion/NotionBlockSheets.js +206 -0
  42. package/lib/features/notion/NotionBlockSheets.js.map +1 -0
  43. package/lib/features/notion/NotionBlockView.js +36 -0
  44. package/lib/features/notion/NotionBlockView.js.map +1 -0
  45. package/lib/features/notion/NotionCommentsSheet.js +461 -0
  46. package/lib/features/notion/NotionCommentsSheet.js.map +1 -0
  47. package/lib/features/notion/NotionConnectionsSheet.js +244 -0
  48. package/lib/features/notion/NotionConnectionsSheet.js.map +1 -0
  49. package/lib/features/notion/NotionHistorySheet.js +439 -0
  50. package/lib/features/notion/NotionHistorySheet.js.map +1 -0
  51. package/lib/features/notion/NotionMediaBlocks.js +803 -0
  52. package/lib/features/notion/NotionMediaBlocks.js.map +1 -0
  53. package/lib/features/notion/NotionMentionSheet.js +279 -0
  54. package/lib/features/notion/NotionMentionSheet.js.map +1 -0
  55. package/lib/features/notion/NotionPageMenu.js +585 -0
  56. package/lib/features/notion/NotionPageMenu.js.map +1 -0
  57. package/lib/features/notion/NotionPageTree.js +220 -0
  58. package/lib/features/notion/NotionPageTree.js.map +1 -0
  59. package/lib/features/notion/NotionPageView.js +1253 -152
  60. package/lib/features/notion/NotionPageView.js.map +1 -1
  61. package/lib/features/notion/NotionShareSheet.js +606 -0
  62. package/lib/features/notion/NotionShareSheet.js.map +1 -0
  63. package/lib/features/notion/NotionSheets.js +87 -15
  64. package/lib/features/notion/NotionSheets.js.map +1 -1
  65. package/lib/features/notion/NotionSidebarSections.js +492 -0
  66. package/lib/features/notion/NotionSidebarSections.js.map +1 -0
  67. package/lib/features/notion/NotionWorkspaceAdmin.js +659 -0
  68. package/lib/features/notion/NotionWorkspaceAdmin.js.map +1 -0
  69. package/lib/features/notion/NotionWorkspaceView.js +257 -45
  70. package/lib/features/notion/NotionWorkspaceView.js.map +1 -1
  71. package/lib/features/notion/database/DatabaseCells.js +554 -0
  72. package/lib/features/notion/database/DatabaseCells.js.map +1 -0
  73. package/lib/features/notion/database/DatabaseDateLayouts.js +792 -0
  74. package/lib/features/notion/database/DatabaseDateLayouts.js.map +1 -0
  75. package/lib/features/notion/database/DatabaseLayouts.js +461 -0
  76. package/lib/features/notion/database/DatabaseLayouts.js.map +1 -0
  77. package/lib/features/notion/database/DatabaseSheets.js +791 -0
  78. package/lib/features/notion/database/DatabaseSheets.js.map +1 -0
  79. package/lib/features/notion/database/NotionDatabaseView.js +817 -0
  80. package/lib/features/notion/database/NotionDatabaseView.js.map +1 -0
  81. package/lib/features/notion/database/RowPropertiesPanel.js +162 -0
  82. package/lib/features/notion/database/RowPropertiesPanel.js.map +1 -0
  83. package/lib/features/notion/database/chartData.js +89 -0
  84. package/lib/features/notion/database/chartData.js.map +1 -0
  85. package/lib/features/notion/database/chartView.js +112 -0
  86. package/lib/features/notion/database/chartView.js.map +1 -0
  87. package/lib/features/notion/database/connectorButton.js +33 -0
  88. package/lib/features/notion/database/connectorButton.js.map +1 -0
  89. package/lib/features/notion/database/databaseCalc.js +208 -0
  90. package/lib/features/notion/database/databaseCalc.js.map +1 -0
  91. package/lib/features/notion/database/databaseCalendar.js +157 -0
  92. package/lib/features/notion/database/databaseCalendar.js.map +1 -0
  93. package/lib/features/notion/database/databaseCsv.js +98 -0
  94. package/lib/features/notion/database/databaseCsv.js.map +1 -0
  95. package/lib/features/notion/database/databaseCsvActions.js +58 -0
  96. package/lib/features/notion/database/databaseCsvActions.js.map +1 -0
  97. package/lib/features/notion/database/databaseFilter.js +473 -0
  98. package/lib/features/notion/database/databaseFilter.js.map +1 -0
  99. package/lib/features/notion/database/databaseFormula.js +1072 -0
  100. package/lib/features/notion/database/databaseFormula.js.map +1 -0
  101. package/lib/features/notion/database/databaseGroup.js +151 -0
  102. package/lib/features/notion/database/databaseGroup.js.map +1 -0
  103. package/lib/features/notion/database/databaseRollup.js +58 -0
  104. package/lib/features/notion/database/databaseRollup.js.map +1 -0
  105. package/lib/features/notion/database/databaseTimeline.js +156 -0
  106. package/lib/features/notion/database/databaseTimeline.js.map +1 -0
  107. package/lib/features/notion/database/databaseView.js +1188 -0
  108. package/lib/features/notion/database/databaseView.js.map +1 -0
  109. package/lib/features/notion/database/databaseViews.js +310 -0
  110. package/lib/features/notion/database/databaseViews.js.map +1 -0
  111. package/lib/features/notion/database/relationSource.js +92 -0
  112. package/lib/features/notion/database/relationSource.js.map +1 -0
  113. package/lib/features/notion/database/uniqueId.js +17 -0
  114. package/lib/features/notion/database/uniqueId.js.map +1 -0
  115. package/lib/features/notion/database/useNotionDatabase.js +617 -0
  116. package/lib/features/notion/database/useNotionDatabase.js.map +1 -0
  117. package/lib/features/notion/notionAgentRunStatus.js +39 -0
  118. package/lib/features/notion/notionAgentRunStatus.js.map +1 -0
  119. package/lib/features/notion/notionCodeLanguages.js +112 -0
  120. package/lib/features/notion/notionCodeLanguages.js.map +1 -0
  121. package/lib/features/notion/notionComments.js +86 -0
  122. package/lib/features/notion/notionComments.js.map +1 -0
  123. package/lib/features/notion/notionConnections.js +74 -0
  124. package/lib/features/notion/notionConnections.js.map +1 -0
  125. package/lib/features/notion/notionDocuments.js +453 -1
  126. package/lib/features/notion/notionDocuments.js.map +1 -1
  127. package/lib/features/notion/notionEditorModel.js +142 -7
  128. package/lib/features/notion/notionEditorModel.js.map +1 -1
  129. package/lib/features/notion/notionMarkdownShortcuts.js +51 -0
  130. package/lib/features/notion/notionMarkdownShortcuts.js.map +1 -0
  131. package/lib/features/notion/notionMedia.js +119 -0
  132. package/lib/features/notion/notionMedia.js.map +1 -0
  133. package/lib/features/notion/notionMentionDate.js +32 -0
  134. package/lib/features/notion/notionMentionDate.js.map +1 -0
  135. package/lib/features/notion/notionMentionOptions.js +162 -0
  136. package/lib/features/notion/notionMentionOptions.js.map +1 -0
  137. package/lib/features/notion/notionNotesAgent.js +445 -0
  138. package/lib/features/notion/notionNotesAgent.js.map +1 -0
  139. package/lib/features/notion/notionPageAccess.js +168 -0
  140. package/lib/features/notion/notionPageAccess.js.map +1 -0
  141. package/lib/features/notion/notionPageActions.js +138 -0
  142. package/lib/features/notion/notionPageActions.js.map +1 -0
  143. package/lib/features/notion/notionPageHistory.js +154 -0
  144. package/lib/features/notion/notionPageHistory.js.map +1 -0
  145. package/lib/features/notion/notionPageKinds.js +200 -0
  146. package/lib/features/notion/notionPageKinds.js.map +1 -0
  147. package/lib/features/notion/notionRecents.js +48 -0
  148. package/lib/features/notion/notionRecents.js.map +1 -0
  149. package/lib/features/notion/notionRichText.js +177 -0
  150. package/lib/features/notion/notionRichText.js.map +1 -0
  151. package/lib/features/notion/notionRichTitle.js +336 -0
  152. package/lib/features/notion/notionRichTitle.js.map +1 -0
  153. package/lib/features/notion/useNotionWorkspace.js +272 -13
  154. package/lib/features/notion/useNotionWorkspace.js.map +1 -1
  155. package/lib/features/notion/usePageActions.js +155 -0
  156. package/lib/features/notion/usePageActions.js.map +1 -0
  157. package/lib/features/resume/ResumeAgentChatPane.js +1 -1
  158. package/lib/features/resume/ResumeAgentChatPane.js.map +1 -1
  159. package/lib/features/shopping/ShoppingAgentChatPane.js +1 -1
  160. package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -1
  161. package/lib/features/study/StudyAgentChatPane.js +1 -1
  162. package/lib/features/study/StudyAgentChatPane.js.map +1 -1
  163. package/lib/features/travel/TravelAgentChatPane.js +1 -1
  164. package/lib/features/travel/TravelAgentChatPane.js.map +1 -1
  165. package/lib/features/webbuilder/WebBuilderExperience.js +40 -8
  166. package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
  167. package/lib/features/webbuilder/buildFragments.js +1 -1
  168. package/lib/features/webbuilder/buildFragments.js.map +1 -1
  169. package/lib/features/webbuilder/codeFiles.js +302 -0
  170. package/lib/features/webbuilder/codeFiles.js.map +1 -0
  171. package/lib/features/webbuilder/codeHighlight.js +209 -0
  172. package/lib/features/webbuilder/codeHighlight.js.map +1 -0
  173. package/lib/features/webbuilder/components/CodeView.js +682 -52
  174. package/lib/features/webbuilder/components/CodeView.js.map +1 -1
  175. package/lib/features/webbuilder/components/PreviewScreen.js +59 -38
  176. package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
  177. package/lib/features/webbuilder/components/ProjectChat.js +3 -3
  178. package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
  179. package/lib/features/webbuilder/stepLabels.js +68 -0
  180. package/lib/features/webbuilder/stepLabels.js.map +1 -0
  181. package/lib/hooks/useHostChatSteering.js +45 -0
  182. package/lib/hooks/useHostChatSteering.js.map +1 -0
  183. package/lib/screens/Chat/index.js +2 -12
  184. package/lib/screens/Chat/index.js.map +1 -1
  185. package/lib/screens/ExpensesNative/useExpensesHostChat.js +25 -5
  186. package/lib/screens/ExpensesNative/useExpensesHostChat.js.map +1 -1
  187. package/lib/screens/InboxNative/useInboxHostChat.js +25 -5
  188. package/lib/screens/InboxNative/useInboxHostChat.js.map +1 -1
  189. package/lib/screens/JobSearchNative/useJobSearchHostChat.js +25 -5
  190. package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
  191. package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js +25 -5
  192. package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js.map +1 -1
  193. package/lib/screens/MoviesNative/useMoviesHostChat.js +25 -5
  194. package/lib/screens/MoviesNative/useMoviesHostChat.js.map +1 -1
  195. package/lib/screens/NotionPage/index.js +2 -2
  196. package/lib/screens/NotionPage/index.js.map +1 -1
  197. package/lib/screens/ResumeNative/useResumeHostChat.js +25 -5
  198. package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
  199. package/lib/screens/ShoppingNative/useShoppingHostChat.js +25 -5
  200. package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
  201. package/lib/screens/StudyNative/useStudyHostChat.js +25 -5
  202. package/lib/screens/StudyNative/useStudyHostChat.js.map +1 -1
  203. package/lib/screens/TravelNative/useTravelHostChat.js +25 -5
  204. package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
  205. package/lib/screens/WebBuilderNative/codeWorkspaceApi.js +222 -0
  206. package/lib/screens/WebBuilderNative/codeWorkspaceApi.js.map +1 -0
  207. package/lib/screens/WebBuilderNative/index.js +1 -1
  208. package/lib/screens/WebBuilderNative/index.js.map +1 -1
  209. package/lib/screens/WebBuilderNative/sandboxProxyApi.js +126 -4
  210. package/lib/screens/WebBuilderNative/sandboxProxyApi.js.map +1 -1
  211. package/lib/screens/WebBuilderNative/useWebBuilderHost.js +120 -11
  212. package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
  213. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import {isPageBlock,blockTitle}from'./notionBlocks.js';var __defProp = Object.defineProperty;
1
+ import {isPageBlock}from'./notionBlocks.js';import {runsText}from'./notionRichTitle.js';import {titleRunsOf}from'./notionRichText.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -66,11 +66,11 @@ const TURN_INTO = [{
66
66
  function isTextType(type) {
67
67
  return TEXT_TYPES.includes(type);
68
68
  }
69
+ const LAYOUT_TYPES = ["column_list", "column"];
69
70
  function nextTypeAfter(type) {
70
71
  return type === "bulleted_list" || type === "numbered_list" || type === "todo" ? type : "paragraph";
71
72
  }
72
- function modelFromTree(tree) {
73
- const rootId = tree.block.id;
73
+ function modelFromTree(tree, rootId = ((_a) => (_a = tree.block) == null ? void 0 : _a.id)()) {
74
74
  const model = {
75
75
  rootId,
76
76
  blocks: {},
@@ -92,15 +92,27 @@ function modelFromTree(tree) {
92
92
  }
93
93
  function toEditorBlock(b, parentId) {
94
94
  var _a;
95
+ const runs = titleRunsOf(b.properties);
95
96
  return {
96
97
  id: b.id,
97
98
  type: b.type,
98
99
  parentId,
99
- text: blockTitle(b),
100
+ text: runsText(runs),
101
+ runs,
100
102
  properties: (_a = b.properties) != null ? _a : {}
101
103
  };
102
104
  }
103
- function flattenModel(model) {
105
+ function emptyBlock(id, type, parentId, properties) {
106
+ return {
107
+ id,
108
+ type,
109
+ parentId,
110
+ text: "",
111
+ runs: [],
112
+ properties
113
+ };
114
+ }
115
+ function flattenModel(model, collapsed = /* @__PURE__ */ new Set()) {
104
116
  const lines = [];
105
117
  const walk = (parentId, depth) => {
106
118
  var _a;
@@ -108,6 +120,11 @@ function flattenModel(model) {
108
120
  ((_a = model.children[parentId]) != null ? _a : []).forEach((id) => {
109
121
  const block = model.blocks[id];
110
122
  if (!block) return;
123
+ if (LAYOUT_TYPES.includes(block.type)) {
124
+ run = 0;
125
+ walk(id, depth);
126
+ return;
127
+ }
111
128
  run = block.type === "numbered_list" ? run + 1 : 0;
112
129
  lines.push(__spreadValues({
113
130
  block,
@@ -115,7 +132,7 @@ function flattenModel(model) {
115
132
  }, block.type === "numbered_list" ? {
116
133
  number: run
117
134
  } : {}));
118
- if (!isPageBlock(block)) walk(id, depth + 1);
135
+ if (!isPageBlock(block) && !(block.type === "toggle" && collapsed.has(id))) walk(id, depth + 1);
119
136
  });
120
137
  };
121
138
  walk(model.rootId, 0);
@@ -177,4 +194,122 @@ function newBlockId() {
177
194
  const r = Math.random() * 16 | 0;
178
195
  return (ch === "x" ? r : r & 3 | 8).toString(16);
179
196
  });
180
- }export{TEXT_TYPES,TURN_INTO,flattenModel,insertAfter,isTextType,modelFromTree,newBlockId,nextTypeAfter,patchBlock,previousLineId,removeBlock};//# sourceMappingURL=notionEditorModel.js.map
197
+ }
198
+ function moveAmongSiblings(model, id, direction) {
199
+ var _a;
200
+ const block = model.blocks[id];
201
+ if (!block) return null;
202
+ const siblings = [...(_a = model.children[block.parentId]) != null ? _a : []];
203
+ const at = siblings.indexOf(id);
204
+ const to = at + direction;
205
+ if (at < 0 || to < 0 || to >= siblings.length) return null;
206
+ [siblings[at], siblings[to]] = [siblings[to], siblings[at]];
207
+ return {
208
+ model: __spreadProps(__spreadValues({}, model), {
209
+ children: __spreadProps(__spreadValues({}, model.children), {
210
+ [block.parentId]: siblings
211
+ })
212
+ }),
213
+ parentId: block.parentId,
214
+ order: siblings
215
+ };
216
+ }
217
+ function snapshotSubtree(model, id) {
218
+ var _a;
219
+ const block = model.blocks[id];
220
+ if (!block) return null;
221
+ const blocks = {};
222
+ const children = {};
223
+ const walk = (bid) => {
224
+ const b = model.blocks[bid];
225
+ if (!b) return;
226
+ blocks[bid] = b;
227
+ const kids = model.children[bid];
228
+ if (kids) {
229
+ children[bid] = [...kids];
230
+ kids.forEach(walk);
231
+ }
232
+ };
233
+ walk(id);
234
+ const index = ((_a = model.children[block.parentId]) != null ? _a : []).indexOf(id);
235
+ return {
236
+ id,
237
+ parentId: block.parentId,
238
+ index,
239
+ blocks,
240
+ children
241
+ };
242
+ }
243
+ function restoreSubtree(model, snap) {
244
+ var _a;
245
+ const siblings = [...(_a = model.children[snap.parentId]) != null ? _a : []].filter((x) => x !== snap.id);
246
+ siblings.splice(Math.max(0, Math.min(snap.index, siblings.length)), 0, snap.id);
247
+ return __spreadProps(__spreadValues({}, model), {
248
+ blocks: __spreadValues(__spreadValues({}, model.blocks), snap.blocks),
249
+ children: __spreadProps(__spreadValues(__spreadValues({}, model.children), snap.children), {
250
+ [snap.parentId]: siblings
251
+ })
252
+ });
253
+ }
254
+ function columnLayout(n, newId = newBlockId) {
255
+ const ratio = Math.round(1 / n * 1e3) / 1e3;
256
+ return {
257
+ id: newId(),
258
+ type: "column_list",
259
+ properties: {},
260
+ children: Array.from({
261
+ length: n
262
+ }, () => ({
263
+ id: newId(),
264
+ type: "column",
265
+ properties: {
266
+ widthRatio: ratio
267
+ },
268
+ children: [{
269
+ id: newId(),
270
+ type: "paragraph",
271
+ properties: {
272
+ title: []
273
+ }
274
+ }]
275
+ }))
276
+ };
277
+ }
278
+ function insertTree(model, tree, parentId, afterId) {
279
+ var _a, _b, _c;
280
+ let next = insertAfter(model, emptyBlock(tree.id, tree.type, parentId, tree.properties), afterId);
281
+ let last = null;
282
+ ((_a = tree.children) != null ? _a : []).forEach((child) => {
283
+ next = insertTree(next, child, tree.id, last);
284
+ last = child.id;
285
+ });
286
+ if (!((_b = tree.children) != null ? _b : []).length) next = __spreadProps(__spreadValues({}, next), {
287
+ children: __spreadProps(__spreadValues({}, next.children), {
288
+ [tree.id]: (_c = next.children[tree.id]) != null ? _c : []
289
+ })
290
+ });
291
+ return next;
292
+ }
293
+ function treeInput(tree, parentId) {
294
+ var _a;
295
+ return __spreadValues({
296
+ id: tree.id,
297
+ type: tree.type,
298
+ parent: {
299
+ type: "block",
300
+ id: parentId
301
+ },
302
+ properties: tree.properties
303
+ }, ((_a = tree.children) == null ? void 0 : _a.length) ? {
304
+ children: tree.children.map((c) => treeInput(c, tree.id))
305
+ } : {});
306
+ }
307
+ function firstTextId(tree) {
308
+ var _a;
309
+ if (TEXT_TYPES.includes(tree.type)) return tree.id;
310
+ for (const c of (_a = tree.children) != null ? _a : []) {
311
+ const hit = firstTextId(c);
312
+ if (hit) return hit;
313
+ }
314
+ return null;
315
+ }export{LAYOUT_TYPES,TEXT_TYPES,TURN_INTO,columnLayout,emptyBlock,firstTextId,flattenModel,insertAfter,insertTree,isTextType,modelFromTree,moveAmongSiblings,newBlockId,nextTypeAfter,patchBlock,previousLineId,removeBlock,restoreSubtree,snapshotSubtree,toEditorBlock,treeInput};//# sourceMappingURL=notionEditorModel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notionEditorModel.js","sources":["../../../src/features/notion/notionEditorModel.ts"],"sourcesContent":["/**\n * Local, optimistic model of an open page for the native editor: blocks by\n * id plus each parent's ordered child ids. Edits apply here first and are\n * sent to the server in the background, so typing never waits on the network.\n *\n * Pure: no RN imports, so it runs under jest as-is.\n */\nimport { blockTitle, isPageBlock, type NotionBlock, type NotionBlockTree } from './notionBlocks';\n\nexport interface EditorBlock {\n id: string;\n type: string;\n parentId: string;\n text: string;\n properties: Record<string, unknown>;\n}\n\nexport interface EditorModel {\n rootId: string;\n blocks: Record<string, EditorBlock>;\n children: Record<string, string[]>;\n}\n\nexport interface EditorLine {\n block: EditorBlock;\n depth: number;\n number?: number;\n}\n\n/** Block types the editor edits as text. */\nexport const TEXT_TYPES: readonly string[] = [\n 'paragraph',\n 'text',\n 'heading_1',\n 'heading_2',\n 'heading_3',\n 'bulleted_list',\n 'numbered_list',\n 'todo',\n 'toggle',\n 'quote',\n 'callout',\n 'code',\n];\n\n/** Types a block can be turned into from the editor toolbar (web slash menu basics). */\nexport const TURN_INTO: ReadonlyArray<{ type: string; label: string; short: string }> = [\n { type: 'paragraph', label: 'Text', short: 'Aa' },\n { type: 'heading_1', label: 'Heading 1', short: 'H1' },\n { type: 'heading_2', label: 'Heading 2', short: 'H2' },\n { type: 'heading_3', label: 'Heading 3', short: 'H3' },\n { type: 'bulleted_list', label: 'Bulleted list', short: '•' },\n { type: 'numbered_list', label: 'Numbered list', short: '1.' },\n { type: 'todo', label: 'To-do', short: '☐' },\n { type: 'toggle', label: 'Toggle', short: '▸' },\n { type: 'quote', label: 'Quote', short: '❝' },\n { type: 'callout', label: 'Callout', short: '💡' },\n { type: 'code', label: 'Code', short: '</>' },\n];\n\nexport function isTextType(type: string): boolean {\n return TEXT_TYPES.includes(type);\n}\n\n/** Return in a list / to-do continues it; anything else starts a paragraph. */\nexport function nextTypeAfter(type: string): string {\n return type === 'bulleted_list' || type === 'numbered_list' || type === 'todo' ? type : 'paragraph';\n}\n\nexport function modelFromTree(tree: NotionBlockTree): EditorModel {\n const rootId = tree.block.id;\n const model: EditorModel = { rootId, blocks: {}, children: {} };\n const walk = (nodes: readonly NotionBlockTree[] | null | undefined, parentId: string) => {\n const ids: string[] = [];\n (nodes ?? []).forEach((node) => {\n const b = node?.block;\n if (!b || b.inTrash || b.archived) return;\n ids.push(b.id);\n model.blocks[b.id] = toEditorBlock(b, parentId);\n if (!isPageBlock(b)) walk(node.children, b.id);\n });\n model.children[parentId] = ids;\n };\n walk(tree.children, rootId);\n return model;\n}\n\nfunction toEditorBlock(b: NotionBlock, parentId: string): EditorBlock {\n return {\n id: b.id,\n type: b.type,\n parentId,\n text: blockTitle(b),\n properties: (b.properties ?? {}) as Record<string, unknown>,\n };\n}\n\n/** Depth-first lines in reading order, numbering runs of numbered_list siblings. */\nexport function flattenModel(model: EditorModel): EditorLine[] {\n const lines: EditorLine[] = [];\n const walk = (parentId: string, depth: number) => {\n let run = 0;\n (model.children[parentId] ?? []).forEach((id) => {\n const block = model.blocks[id];\n if (!block) return;\n run = block.type === 'numbered_list' ? run + 1 : 0;\n lines.push({ block, depth, ...(block.type === 'numbered_list' ? { number: run } : {}) });\n if (!isPageBlock(block)) walk(id, depth + 1);\n });\n };\n walk(model.rootId, 0);\n return lines;\n}\n\n/** Insert `block` under its parent right after `afterId` (end when absent or not found). */\nexport function insertAfter(model: EditorModel, block: EditorBlock, afterId?: string | null): EditorModel {\n const siblings = [...(model.children[block.parentId] ?? [])];\n const at = afterId ? siblings.indexOf(afterId) : -1;\n if (at >= 0) siblings.splice(at + 1, 0, block.id);\n else siblings.push(block.id);\n return {\n ...model,\n blocks: { ...model.blocks, [block.id]: block },\n children: { ...model.children, [block.parentId]: siblings },\n };\n}\n\n/** Remove a block and its subtree. */\nexport function removeBlock(model: EditorModel, id: string): EditorModel {\n const block = model.blocks[id];\n if (!block) return model;\n const blocks = { ...model.blocks };\n const children = { ...model.children };\n const drop = (bid: string) => {\n (children[bid] ?? []).forEach(drop);\n delete children[bid];\n delete blocks[bid];\n };\n drop(id);\n children[block.parentId] = (children[block.parentId] ?? []).filter((x) => x !== id);\n return { ...model, blocks, children };\n}\n\nexport function patchBlock(model: EditorModel, id: string, patch: Partial<EditorBlock>): EditorModel {\n const block = model.blocks[id];\n if (!block) return model;\n return { ...model, blocks: { ...model.blocks, [id]: { ...block, ...patch } } };\n}\n\n/** The line before `id` in reading order (where focus goes after deleting it). */\nexport function previousLineId(model: EditorModel, id: string): string | null {\n const lines = flattenModel(model);\n const at = lines.findIndex((l) => l.block.id === id);\n for (let i = at - 1; i >= 0; i -= 1) if (isTextType(lines[i].block.type)) return lines[i].block.id;\n return null;\n}\n\n/** Client-chosen block id (the server accepts `input.id` on create). */\nexport function newBlockId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n // eslint-disable-next-line no-bitwise\n const r = (Math.random() * 16) | 0;\n // eslint-disable-next-line no-bitwise\n return (ch === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"notionEditorModel.js","sources":["../../../src/features/notion/notionEditorModel.ts"],"sourcesContent":["/**\n * Local, optimistic model of an open page for the native editor: blocks by\n * id plus each parent's ordered child ids. Edits apply here first and are\n * sent to the server in the background, so typing never waits on the network.\n *\n * Pure: no RN imports, so it runs under jest as-is.\n */\nimport { isPageBlock, type NotionBlock, type NotionBlockTree } from './notionBlocks';\nimport { runsText, type RichRun } from './notionRichTitle';\nimport { titleRunsOf } from './notionRichText';\n\nexport interface EditorBlock {\n id: string;\n type: string;\n parentId: string;\n /** Plain text of `runs` (what the TextInput edits). */\n text: string;\n /** Formatted runs of the title (bold, colours, links, mentions) - what is saved. */\n runs: RichRun[];\n properties: Record<string, unknown>;\n}\n\nexport interface EditorModel {\n rootId: string;\n blocks: Record<string, EditorBlock>;\n children: Record<string, string[]>;\n}\n\nexport interface EditorLine {\n block: EditorBlock;\n depth: number;\n number?: number;\n}\n\n/** Block types the editor edits as text. */\nexport const TEXT_TYPES: readonly string[] = [\n 'paragraph',\n 'text',\n 'heading_1',\n 'heading_2',\n 'heading_3',\n 'bulleted_list',\n 'numbered_list',\n 'todo',\n 'toggle',\n 'quote',\n 'callout',\n 'code',\n];\n\n/** Types a block can be turned into from the editor toolbar (web slash menu basics). */\nexport const TURN_INTO: ReadonlyArray<{ type: string; label: string; short: string }> = [\n { type: 'paragraph', label: 'Text', short: 'Aa' },\n { type: 'heading_1', label: 'Heading 1', short: 'H1' },\n { type: 'heading_2', label: 'Heading 2', short: 'H2' },\n { type: 'heading_3', label: 'Heading 3', short: 'H3' },\n { type: 'bulleted_list', label: 'Bulleted list', short: '•' },\n { type: 'numbered_list', label: 'Numbered list', short: '1.' },\n { type: 'todo', label: 'To-do', short: '☐' },\n { type: 'toggle', label: 'Toggle', short: '▸' },\n { type: 'quote', label: 'Quote', short: '❝' },\n { type: 'callout', label: 'Callout', short: '💡' },\n { type: 'code', label: 'Code', short: '</>' },\n];\n\nexport function isTextType(type: string): boolean {\n return TEXT_TYPES.includes(type);\n}\n\n/** Layout containers with no content of their own (web column_list / column). */\nexport const LAYOUT_TYPES: readonly string[] = ['column_list', 'column'];\n\n/** Return in a list / to-do continues it; anything else starts a paragraph. */\nexport function nextTypeAfter(type: string): string {\n return type === 'bulleted_list' || type === 'numbered_list' || type === 'todo' ? type : 'paragraph';\n}\n\n/**\n * `rootId` is the page id the caller already knows: the tree's root block can come back\n * without its fields on device (no id / title), and new top-level blocks are parented to it.\n */\nexport function modelFromTree(tree: NotionBlockTree, rootId: string = tree.block?.id): EditorModel {\n const model: EditorModel = { rootId, blocks: {}, children: {} };\n const walk = (nodes: readonly NotionBlockTree[] | null | undefined, parentId: string) => {\n const ids: string[] = [];\n (nodes ?? []).forEach((node) => {\n const b = node?.block;\n if (!b || b.inTrash || b.archived) return;\n ids.push(b.id);\n model.blocks[b.id] = toEditorBlock(b, parentId);\n if (!isPageBlock(b)) walk(node.children, b.id);\n });\n model.children[parentId] = ids;\n };\n walk(tree.children, rootId);\n return model;\n}\n\nexport function toEditorBlock(b: NotionBlock, parentId: string): EditorBlock {\n const runs = titleRunsOf(b.properties);\n return {\n id: b.id,\n type: b.type,\n parentId,\n text: runsText(runs),\n runs,\n properties: (b.properties ?? {}) as Record<string, unknown>,\n };\n}\n\n/** A fresh, empty block (local, before the server has it). */\nexport function emptyBlock(\n id: string,\n type: string,\n parentId: string,\n properties: Record<string, unknown>,\n): EditorBlock {\n return { id, type, parentId, text: '', runs: [], properties };\n}\n\n/**\n * Depth-first lines in reading order, numbering runs of numbered_list siblings. Children of a\n * toggle listed in `collapsed` are hidden (Notion toggles open on tap).\n */\nexport function flattenModel(model: EditorModel, collapsed: ReadonlySet<string> = new Set()): EditorLine[] {\n const lines: EditorLine[] = [];\n const walk = (parentId: string, depth: number) => {\n let run = 0;\n (model.children[parentId] ?? []).forEach((id) => {\n const block = model.blocks[id];\n if (!block) return;\n // Column layouts are transparent on a phone: their blocks read top to bottom at the\n // same indent (the web shows them side by side).\n if (LAYOUT_TYPES.includes(block.type)) {\n run = 0;\n walk(id, depth);\n return;\n }\n run = block.type === 'numbered_list' ? run + 1 : 0;\n lines.push({ block, depth, ...(block.type === 'numbered_list' ? { number: run } : {}) });\n if (!isPageBlock(block) && !(block.type === 'toggle' && collapsed.has(id))) walk(id, depth + 1);\n });\n };\n walk(model.rootId, 0);\n return lines;\n}\n\n/** Insert `block` under its parent right after `afterId` (end when absent or not found). */\nexport function insertAfter(model: EditorModel, block: EditorBlock, afterId?: string | null): EditorModel {\n const siblings = [...(model.children[block.parentId] ?? [])];\n const at = afterId ? siblings.indexOf(afterId) : -1;\n if (at >= 0) siblings.splice(at + 1, 0, block.id);\n else siblings.push(block.id);\n return {\n ...model,\n blocks: { ...model.blocks, [block.id]: block },\n children: { ...model.children, [block.parentId]: siblings },\n };\n}\n\n/** Remove a block and its subtree. */\nexport function removeBlock(model: EditorModel, id: string): EditorModel {\n const block = model.blocks[id];\n if (!block) return model;\n const blocks = { ...model.blocks };\n const children = { ...model.children };\n const drop = (bid: string) => {\n (children[bid] ?? []).forEach(drop);\n delete children[bid];\n delete blocks[bid];\n };\n drop(id);\n children[block.parentId] = (children[block.parentId] ?? []).filter((x) => x !== id);\n return { ...model, blocks, children };\n}\n\nexport function patchBlock(model: EditorModel, id: string, patch: Partial<EditorBlock>): EditorModel {\n const block = model.blocks[id];\n if (!block) return model;\n return { ...model, blocks: { ...model.blocks, [id]: { ...block, ...patch } } };\n}\n\n/** The line before `id` in reading order (where focus goes after deleting it). */\nexport function previousLineId(model: EditorModel, id: string): string | null {\n const lines = flattenModel(model);\n const at = lines.findIndex((l) => l.block.id === id);\n for (let i = at - 1; i >= 0; i -= 1) if (isTextType(lines[i].block.type)) return lines[i].block.id;\n return null;\n}\n\n/** Client-chosen block id (the server accepts `input.id` on create). */\nexport function newBlockId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n // eslint-disable-next-line no-bitwise\n const r = (Math.random() * 16) | 0;\n // eslint-disable-next-line no-bitwise\n return (ch === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n\n/**\n * Move a block one place up or down among its siblings. Returns the new sibling order (to send\n * as reorderChildren) or null when it is already at that end.\n */\nexport function moveAmongSiblings(\n model: EditorModel,\n id: string,\n direction: -1 | 1,\n): { model: EditorModel; parentId: string; order: string[] } | null {\n const block = model.blocks[id];\n if (!block) return null;\n const siblings = [...(model.children[block.parentId] ?? [])];\n const at = siblings.indexOf(id);\n const to = at + direction;\n if (at < 0 || to < 0 || to >= siblings.length) return null;\n [siblings[at], siblings[to]] = [siblings[to], siblings[at]];\n return {\n model: { ...model, children: { ...model.children, [block.parentId]: siblings } },\n parentId: block.parentId,\n order: siblings,\n };\n}\n\n/** A removed block with everything under it and where it sat - what Undo puts back. */\nexport interface SubtreeSnapshot {\n id: string;\n parentId: string;\n index: number;\n blocks: Record<string, EditorBlock>;\n children: Record<string, string[]>;\n}\n\nexport function snapshotSubtree(model: EditorModel, id: string): SubtreeSnapshot | null {\n const block = model.blocks[id];\n if (!block) return null;\n const blocks: Record<string, EditorBlock> = {};\n const children: Record<string, string[]> = {};\n const walk = (bid: string) => {\n const b = model.blocks[bid];\n if (!b) return;\n blocks[bid] = b;\n const kids = model.children[bid];\n if (kids) {\n children[bid] = [...kids];\n kids.forEach(walk);\n }\n };\n walk(id);\n const index = (model.children[block.parentId] ?? []).indexOf(id);\n return { id, parentId: block.parentId, index, blocks, children };\n}\n\n/** Put a snapshot back at its old position (clamped to the current siblings). */\nexport function restoreSubtree(model: EditorModel, snap: SubtreeSnapshot): EditorModel {\n const siblings = [...(model.children[snap.parentId] ?? [])].filter((x) => x !== snap.id);\n siblings.splice(Math.max(0, Math.min(snap.index, siblings.length)), 0, snap.id);\n return {\n ...model,\n blocks: { ...model.blocks, ...snap.blocks },\n children: { ...model.children, ...snap.children, [snap.parentId]: siblings },\n };\n}\n\n/** A block to create with its nested children (one appendChildren call, client ids). */\nexport interface NewBlockTree {\n id: string;\n type: string;\n properties: Record<string, unknown>;\n children?: NewBlockTree[];\n}\n\n/** Web \"N columns\": a column_list of N equal columns, each starting with an empty paragraph. */\nexport function columnLayout(n: number, newId: () => string = newBlockId): NewBlockTree {\n const ratio = Math.round((1 / n) * 1000) / 1000;\n return {\n id: newId(),\n type: 'column_list',\n properties: {},\n children: Array.from({ length: n }, () => ({\n id: newId(),\n type: 'column',\n properties: { widthRatio: ratio },\n children: [{ id: newId(), type: 'paragraph', properties: { title: [] } }],\n })),\n };\n}\n\n/** Insert a new block tree locally (after `afterId` under `parentId`). */\nexport function insertTree(\n model: EditorModel,\n tree: NewBlockTree,\n parentId: string,\n afterId?: string | null,\n): EditorModel {\n let next = insertAfter(model, emptyBlock(tree.id, tree.type, parentId, tree.properties), afterId);\n let last: string | null = null;\n (tree.children ?? []).forEach((child) => {\n next = insertTree(next, child, tree.id, last);\n last = child.id;\n });\n if (!(tree.children ?? []).length)\n next = { ...next, children: { ...next.children, [tree.id]: next.children[tree.id] ?? [] } };\n return next;\n}\n\n/** The appendChildren input for a tree (children carry their own parent refs). */\nexport function treeInput(tree: NewBlockTree, parentId: string): Record<string, unknown> {\n return {\n id: tree.id,\n type: tree.type,\n parent: { type: 'block', id: parentId },\n properties: tree.properties,\n ...(tree.children?.length ? { children: tree.children.map((c) => treeInput(c, tree.id)) } : {}),\n };\n}\n\n/** First text block inside a tree (where the caret goes after inserting columns). */\nexport function firstTextId(tree: NewBlockTree): string | null {\n if (TEXT_TYPES.includes(tree.type)) return tree.id;\n for (const c of tree.children ?? []) {\n const hit = firstTextId(c);\n if (hit) return hit;\n }\n return null;\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ function markdownShortcutFor(before, currentType) {
2
+ const headingOk = currentType !== "code";
3
+ switch (before) {
4
+ case "#":
5
+ return headingOk ? {
6
+ type: "heading_1"
7
+ } : null;
8
+ case "##":
9
+ return headingOk ? {
10
+ type: "heading_2"
11
+ } : null;
12
+ case "###":
13
+ return headingOk ? {
14
+ type: "heading_3"
15
+ } : null;
16
+ }
17
+ if (currentType !== "paragraph" && currentType !== "text") return null;
18
+ if (before === "-" || before === "*" || before === "+") return {
19
+ type: "bulleted_list"
20
+ };
21
+ if (/^\d+[.)]$/.test(before)) return {
22
+ type: "numbered_list"
23
+ };
24
+ if (before === "[]" || before === "[ ]") return {
25
+ type: "todo",
26
+ properties: {
27
+ checked: false
28
+ }
29
+ };
30
+ if (before === "[x]" || before === "[X]") return {
31
+ type: "todo",
32
+ properties: {
33
+ checked: true
34
+ }
35
+ };
36
+ if (before === '"' || before === "\u201C") return {
37
+ type: "quote"
38
+ };
39
+ if (before === ">") return {
40
+ type: "toggle"
41
+ };
42
+ if (before === "!>" || before === "\u{1F4A1}") return {
43
+ type: "callout",
44
+ properties: {
45
+ icon: {
46
+ emoji: "\u{1F4A1}"
47
+ }
48
+ }
49
+ };
50
+ return null;
51
+ }export{markdownShortcutFor};//# sourceMappingURL=notionMarkdownShortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notionMarkdownShortcuts.js","sources":["../../../src/features/notion/notionMarkdownShortcuts.ts"],"sourcesContent":["// Ported verbatim from forms-stack packages/notion-api/browser/src/utils/markdownShortcuts.ts (develop).\n/* eslint-disable */\n/**\n * Notion-style markdown shortcuts typed at the start of a block, then Space.\n * (``` and --- fire without a space — see handleDraftTextChange.)\n */\nexport function markdownShortcutFor(\n before: string,\n currentType: string,\n): { type: string; properties?: Record<string, unknown> } | null {\n const headingOk = currentType !== 'code';\n switch (before) {\n case '#':\n return headingOk ? { type: 'heading_1' } : null;\n case '##':\n return headingOk ? { type: 'heading_2' } : null;\n case '###':\n return headingOk ? { type: 'heading_3' } : null;\n }\n // Everything else converts plain text only (not an existing list/heading/todo).\n if (currentType !== 'paragraph' && currentType !== 'text') return null;\n if (before === '-' || before === '*' || before === '+') return { type: 'bulleted_list' };\n if (/^\\d+[.)]$/.test(before)) return { type: 'numbered_list' };\n if (before === '[]' || before === '[ ]') return { type: 'todo', properties: { checked: false } };\n if (before === '[x]' || before === '[X]') return { type: 'todo', properties: { checked: true } };\n if (before === '\"' || before === '“') return { type: 'quote' };\n if (before === '>') return { type: 'toggle' };\n if (before === '!>' || before === '💡') return { type: 'callout', properties: { icon: { emoji: '💡' } } };\n return null;\n}\n"],"names":[],"mappings":"AAMgB,SAAA,mBAAA,CAAoB,QAAgB,WAG3C,EAAA;AACP,EAAA,MAAM,YAAY,WAAgB,KAAA,MAAA;AAClC,EAAA,QAAQ,MAAQ;AAAA,IACd,KAAK,GAAA;AACH,MAAA,OAAO,SAAY,GAAA;AAAA,QACjB,IAAM,EAAA;AAAA,OACJ,GAAA,IAAA;AAAA,IACN,KAAK,IAAA;AACH,MAAA,OAAO,SAAY,GAAA;AAAA,QACjB,IAAM,EAAA;AAAA,OACJ,GAAA,IAAA;AAAA,IACN,KAAK,KAAA;AACH,MAAA,OAAO,SAAY,GAAA;AAAA,QACjB,IAAM,EAAA;AAAA,OACJ,GAAA,IAAA;AAAA;AAGR,EAAA,IAAI,WAAgB,KAAA,WAAA,IAAe,WAAgB,KAAA,MAAA,EAAe,OAAA,IAAA;AAClE,EAAA,IAAI,WAAW,GAAO,IAAA,MAAA,KAAW,GAAO,IAAA,MAAA,KAAW,KAAY,OAAA;AAAA,IAC7D,IAAM,EAAA;AAAA,GACR;AACA,EAAA,IAAI,WAAY,CAAA,IAAA,CAAK,MAAM,CAAA,EAAU,OAAA;AAAA,IACnC,IAAM,EAAA;AAAA,GACR;AACA,EAAA,IAAI,MAAW,KAAA,IAAA,IAAQ,MAAW,KAAA,KAAA,EAAc,OAAA;AAAA,IAC9C,IAAM,EAAA,MAAA;AAAA,IACN,UAAY,EAAA;AAAA,MACV,OAAS,EAAA;AAAA;AACX,GACF;AACA,EAAA,IAAI,MAAW,KAAA,KAAA,IAAS,MAAW,KAAA,KAAA,EAAc,OAAA;AAAA,IAC/C,IAAM,EAAA,MAAA;AAAA,IACN,UAAY,EAAA;AAAA,MACV,OAAS,EAAA;AAAA;AACX,GACF;AACA,EAAA,IAAI,MAAW,KAAA,GAAA,IAAO,MAAW,KAAA,QAAA,EAAY,OAAA;AAAA,IAC3C,IAAM,EAAA;AAAA,GACR;AACA,EAAI,IAAA,MAAA,KAAW,KAAY,OAAA;AAAA,IACzB,IAAM,EAAA;AAAA,GACR;AACA,EAAA,IAAI,MAAW,KAAA,IAAA,IAAQ,MAAW,KAAA,WAAA,EAAa,OAAA;AAAA,IAC7C,IAAM,EAAA,SAAA;AAAA,IACN,UAAY,EAAA;AAAA,MACV,IAAM,EAAA;AAAA,QACJ,KAAO,EAAA;AAAA;AACT;AACF,GACF;AACA,EAAO,OAAA,IAAA;AACT"}
@@ -0,0 +1,119 @@
1
+ function mediaSourceOf(props) {
2
+ var _a, _b, _c;
3
+ const p = props != null ? props : {};
4
+ const managed = p.source === "managed" || !!p.fileInfoId || !!p.storageKey;
5
+ const key = p.storageKey || ((_a = p.file) == null ? void 0 : _a.url);
6
+ if (managed && key) return {
7
+ kind: "managed",
8
+ key
9
+ };
10
+ const url = ((_b = p.external) == null ? void 0 : _b.url) || ((_c = p.file) == null ? void 0 : _c.url) || p.url;
11
+ return typeof url === "string" && /^https?:\/\//i.test(url) ? {
12
+ kind: "external",
13
+ url
14
+ } : null;
15
+ }
16
+ function managedFileProps(file) {
17
+ return {
18
+ source: "managed",
19
+ fileInfoId: file.id,
20
+ storageKey: file.url,
21
+ mimeType: file.mimeType,
22
+ size: file.size,
23
+ file: {
24
+ url: file.url,
25
+ name: file.name,
26
+ size: file.size
27
+ }
28
+ };
29
+ }
30
+ function externalProps(url) {
31
+ return {
32
+ source: null,
33
+ fileInfoId: null,
34
+ storageKey: null,
35
+ external: {
36
+ url: url.trim()
37
+ }
38
+ };
39
+ }
40
+ function fileNameOf(props) {
41
+ var _a, _b;
42
+ const p = props != null ? props : {};
43
+ const name = ((_a = p.file) == null ? void 0 : _a.name) || p.name;
44
+ if (typeof name === "string" && name.trim()) return name.trim();
45
+ const src = mediaSourceOf(p);
46
+ const raw = src ? src.kind === "managed" ? src.key : src.url : "";
47
+ const tail = (_b = raw.split("?")[0].split("/").pop()) != null ? _b : "";
48
+ try {
49
+ return decodeURIComponent(tail) || "File";
50
+ } catch (e) {
51
+ return tail || "File";
52
+ }
53
+ }
54
+ function sizeLabel(bytes) {
55
+ const n = typeof bytes === "number" ? bytes : Number(bytes);
56
+ if (!Number.isFinite(n) || n <= 0) return "";
57
+ if (n < 1024) return `${n} B`;
58
+ if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;
59
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
60
+ }
61
+ function hostOf(url) {
62
+ const m = /^https?:\/\/([^/?#]+)/i.exec(url.trim());
63
+ return m ? m[1].replace(/^www\./, "") : url;
64
+ }
65
+ function isStreamingSiteUrl(url) {
66
+ return /(youtube\.com|youtu\.be|vimeo\.com|loom\.com)/i.test(url);
67
+ }
68
+ function tableRowsOf(props) {
69
+ const raw = props == null ? void 0 : props.rows;
70
+ if (Array.isArray(raw) && raw.length > 0 && Array.isArray(raw[0])) {
71
+ return raw.map((row) => Array.isArray(row) ? row.map((c) => String(c != null ? c : "")) : ["", ""]);
72
+ }
73
+ return [["", ""], ["", ""]];
74
+ }
75
+ function setCell(rows, r, c, value) {
76
+ return rows.map((row, ri) => ri === r ? row.map((cell, ci) => ci === c ? value : cell) : row);
77
+ }
78
+ function addRow(rows) {
79
+ var _a, _b;
80
+ return [...rows, new Array((_b = (_a = rows[0]) == null ? void 0 : _a.length) != null ? _b : 2).fill("")];
81
+ }
82
+ function addColumn(rows) {
83
+ return rows.map((row) => [...row, ""]);
84
+ }
85
+ function removeRow(rows, r) {
86
+ return rows.length > 1 ? rows.filter((_, i) => i !== r) : rows;
87
+ }
88
+ function removeColumn(rows, c) {
89
+ var _a, _b;
90
+ return ((_b = (_a = rows[0]) == null ? void 0 : _a.length) != null ? _b : 0) > 1 ? rows.map((row) => row.filter((_, i) => i !== c)) : rows;
91
+ }
92
+ function contentTypeForS3Put(mimeType, filename) {
93
+ const raw = (mimeType).trim();
94
+ if (/charset\s*=/i.test(raw)) {
95
+ return raw;
96
+ }
97
+ const primary = (raw.split(";")[0] || "").trim().toLowerCase() || "application/octet-stream";
98
+ const textLikeExtensions = /\.(md|markdown|txt|csv|json|ya?ml|yml|env|xml|html?|htm|css|js|mjs|cjs|ts|tsx|jsx|graphql|mdx|svg|log)$/i.test(filename);
99
+ const textLikeMime = primary.startsWith("text/") || primary === "application/json" || primary === "application/xml" || primary === "application/javascript" || primary === "application/x-yaml" || primary === "application/graphql" || primary === "image/svg+xml";
100
+ if (!textLikeMime && !textLikeExtensions) {
101
+ return primary;
102
+ }
103
+ let base = primary;
104
+ if (primary === "application/octet-stream" || primary === "") {
105
+ if (/\.(md|markdown)$/i.test(filename)) base = "text/markdown";
106
+ else if (/\.(ya?ml|yml)$/i.test(filename)) base = "text/yaml";
107
+ else if (/\.json$/i.test(filename)) base = "application/json";
108
+ else if (/\.(html?|htm)$/i.test(filename)) base = "text/html";
109
+ else if (/\.svg$/i.test(filename)) base = "image/svg+xml";
110
+ else if (/\.(css)$/i.test(filename)) base = "text/css";
111
+ else if (/\.(js|mjs|cjs)$/i.test(filename)) base = "text/javascript";
112
+ else if (/\.(ts|tsx|jsx)$/i.test(filename)) base = "text/plain";
113
+ else if (/\.(txt|env|log)$/i.test(filename)) base = "text/plain";
114
+ else if (/\.csv$/i.test(filename)) base = "text/csv";
115
+ else if (/\.xml$/i.test(filename)) base = "application/xml";
116
+ else base = "text/plain";
117
+ }
118
+ return `${base}; charset=utf-8`;
119
+ }export{addColumn,addRow,contentTypeForS3Put,externalProps,fileNameOf,hostOf,isStreamingSiteUrl,managedFileProps,mediaSourceOf,removeColumn,removeRow,setCell,sizeLabel,tableRowsOf};//# sourceMappingURL=notionMedia.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notionMedia.js","sources":["../../../src/features/notion/notionMedia.ts"],"sourcesContent":["/**\n * Media blocks on the same data as the web BlockEditor:\n * - image / video / file / audio: `external.url` (a link) or an uploaded file\n * (`source: 'managed'`, `storageKey`, `file: { url, name, size }`), shown through a\n * short-lived link from resolveNotionFileUrl;\n * - bookmark: `url` + the preview (`title`, `description`, `image`);\n * - embed: `url`; table: `rows` (string grid) + `hasHeaderRow`; equation: `expression`.\n *\n * Pure: no RN imports, so it runs under jest as-is.\n */\n\nexport type MediaSource = { kind: 'managed'; key: string } | { kind: 'external'; url: string } | null;\n\ntype Props = Record<string, any> | null | undefined;\n\n/** Where a media block's bytes live (web: managed wins over external). */\nexport function mediaSourceOf(props: Props): MediaSource {\n const p = props ?? {};\n const managed = p.source === 'managed' || !!p.fileInfoId || !!p.storageKey;\n const key = (p.storageKey || p.file?.url) as string | undefined;\n if (managed && key) return { kind: 'managed', key };\n const url = (p.external?.url || p.file?.url || p.url) as string | undefined;\n return typeof url === 'string' && /^https?:\\/\\//i.test(url) ? { kind: 'external', url } : null;\n}\n\n/** Properties after an upload (web handleFile for image / video / file / audio). */\nexport function managedFileProps(file: { id: string; url: string; name: string; mimeType: string; size: number }) {\n return {\n source: 'managed',\n fileInfoId: file.id,\n storageKey: file.url,\n mimeType: file.mimeType,\n size: file.size,\n file: { url: file.url, name: file.name, size: file.size },\n };\n}\n\n/** Properties for a pasted link (web applyImageUrl / video link). */\nexport function externalProps(url: string) {\n return { source: null, fileInfoId: null, storageKey: null, external: { url: url.trim() } };\n}\n\nexport function fileNameOf(props: Props): string {\n const p = props ?? {};\n const name = p.file?.name || p.name;\n if (typeof name === 'string' && name.trim()) return name.trim();\n const src = mediaSourceOf(p);\n const raw = src ? (src.kind === 'managed' ? src.key : src.url) : '';\n const tail = raw.split('?')[0].split('/').pop() ?? '';\n try {\n return decodeURIComponent(tail) || 'File';\n } catch {\n return tail || 'File';\n }\n}\n\nexport function sizeLabel(bytes: unknown): string {\n const n = typeof bytes === 'number' ? bytes : Number(bytes);\n if (!Number.isFinite(n) || n <= 0) return '';\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;\n return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nexport function hostOf(url: string): string {\n const m = /^https?:\\/\\/([^/?#]+)/i.exec(url.trim());\n return m ? m[1].replace(/^www\\./, '') : url;\n}\n\n/** YouTube / Vimeo / Loom links can't play in a native video player: they open in the browser. */\nexport function isStreamingSiteUrl(url: string): boolean {\n return /(youtube\\.com|youtu\\.be|vimeo\\.com|loom\\.com)/i.test(url);\n}\n\n/** Web getTableRows: a string grid, at least 2 x 2. */\nexport function tableRowsOf(props: Props): string[][] {\n const raw = props?.rows;\n if (Array.isArray(raw) && raw.length > 0 && Array.isArray(raw[0])) {\n return raw.map((row: unknown) => (Array.isArray(row) ? row.map((c) => String(c ?? '')) : ['', '']));\n }\n return [\n ['', ''],\n ['', ''],\n ];\n}\n\nexport function setCell(rows: string[][], r: number, c: number, value: string): string[][] {\n return rows.map((row, ri) => (ri === r ? row.map((cell, ci) => (ci === c ? value : cell)) : row));\n}\n\nexport function addRow(rows: string[][]): string[][] {\n return [...rows, new Array(rows[0]?.length ?? 2).fill('')];\n}\n\nexport function addColumn(rows: string[][]): string[][] {\n return rows.map((row) => [...row, '']);\n}\n\nexport function removeRow(rows: string[][], r: number): string[][] {\n return rows.length > 1 ? rows.filter((_, i) => i !== r) : rows;\n}\n\nexport function removeColumn(rows: string[][], c: number): string[][] {\n return (rows[0]?.length ?? 0) > 1 ? rows.map((row) => row.filter((_, i) => i !== c)) : rows;\n}\n\n/** Content-Type for the S3 PUT - ported verbatim from the web executors (UTF-8 for text files). */\nexport function contentTypeForS3Put(mimeType: string, filename: string): string {\n const raw = (mimeType || '').trim();\n if (/charset\\s*=/i.test(raw)) {\n return raw;\n }\n const primary = (raw.split(';')[0] || '').trim().toLowerCase() || 'application/octet-stream';\n const textLikeExtensions =\n /\\.(md|markdown|txt|csv|json|ya?ml|yml|env|xml|html?|htm|css|js|mjs|cjs|ts|tsx|jsx|graphql|mdx|svg|log)$/i.test(\n filename,\n );\n const textLikeMime =\n primary.startsWith('text/') ||\n primary === 'application/json' ||\n primary === 'application/xml' ||\n primary === 'application/javascript' ||\n primary === 'application/x-yaml' ||\n primary === 'application/graphql' ||\n primary === 'image/svg+xml';\n\n if (!textLikeMime && !textLikeExtensions) {\n return primary;\n }\n\n let base = primary;\n if (primary === 'application/octet-stream' || primary === '') {\n if (/\\.(md|markdown)$/i.test(filename)) base = 'text/markdown';\n else if (/\\.(ya?ml|yml)$/i.test(filename)) base = 'text/yaml';\n else if (/\\.json$/i.test(filename)) base = 'application/json';\n else if (/\\.(html?|htm)$/i.test(filename)) base = 'text/html';\n else if (/\\.svg$/i.test(filename)) base = 'image/svg+xml';\n else if (/\\.(css)$/i.test(filename)) base = 'text/css';\n else if (/\\.(js|mjs|cjs)$/i.test(filename)) base = 'text/javascript';\n else if (/\\.(ts|tsx|jsx)$/i.test(filename)) base = 'text/plain';\n else if (/\\.(txt|env|log)$/i.test(filename)) base = 'text/plain';\n else if (/\\.csv$/i.test(filename)) base = 'text/csv';\n else if (/\\.xml$/i.test(filename)) base = 'application/xml';\n else base = 'text/plain';\n }\n\n return `${base}; charset=utf-8`;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
2
+ const pad = (n) => String(n).padStart(2, "0");
3
+ function toLocalISODate(d) {
4
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
5
+ }
6
+ function parseMentionDate(value) {
7
+ const day = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
8
+ if (day) return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3]));
9
+ const t = Date.parse(value);
10
+ return Number.isNaN(t) ? null : new Date(t);
11
+ }
12
+ function absoluteDateLabel(value) {
13
+ const d = parseMentionDate(value);
14
+ if (!d) return value;
15
+ return `${MONTHS[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
16
+ }
17
+ function datePresets(now = /* @__PURE__ */ new Date()) {
18
+ const plus = (days) => toLocalISODate(new Date(now.getFullYear(), now.getMonth(), now.getDate() + days));
19
+ return [{
20
+ key: "today",
21
+ label: "Today",
22
+ start: plus(0)
23
+ }, {
24
+ key: "tomorrow",
25
+ label: "Tomorrow",
26
+ start: plus(1)
27
+ }, {
28
+ key: "next_week",
29
+ label: "Next week",
30
+ start: plus(7)
31
+ }];
32
+ }export{absoluteDateLabel,datePresets,parseMentionDate,toLocalISODate};//# sourceMappingURL=notionMentionDate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notionMentionDate.js","sources":["../../../src/features/notion/notionMentionDate.ts"],"sourcesContent":["// Ported verbatim from forms-stack packages/notion-api/browser/src/utils/mentionDate.ts (develop).\n/* eslint-disable */\n/**\n * @date and @person mention helpers (pure): stored dates are local calendar days\n * (`YYYY-MM-DD`, optionally a full ISO time); read mode shows them relative to today like\n * Notion (\"@Today\", \"@Tomorrow\", \"@Yesterday\", otherwise \"Jan 23, 2027\").\n */\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\nconst DAY_MS = 86_400_000;\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\n/** Local calendar day of `d` as `YYYY-MM-DD`. */\nexport function toLocalISODate(d: Date): string {\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\n/** Parse a stored mention date. `YYYY-MM-DD` is a LOCAL day (not UTC midnight). */\nexport function parseMentionDate(value: string): Date | null {\n const day = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value);\n if (day) return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3]));\n const t = Date.parse(value);\n return Number.isNaN(t) ? null : new Date(t);\n}\n\nfunction startOfDay(d: Date): number {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\n}\n\n/** Whole days from `now`'s day to `value`'s day (DST-safe). */\nexport function daysFromToday(value: string, now: Date = new Date()): number | null {\n const d = parseMentionDate(value);\n if (!d) return null;\n return Math.round((startOfDay(d) - startOfDay(now)) / DAY_MS);\n}\n\n/** \"Jan 23, 2027\" (absolute; what is stored as the mention's text). */\nexport function absoluteDateLabel(value: string): string {\n const d = parseMentionDate(value);\n if (!d) return value;\n return `${MONTHS[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;\n}\n\n/** Read-mode label: \"Today\" / \"Tomorrow\" / \"Yesterday\", else \"Jan 23, 2027\" (ranges: \"A → B\"). */\nexport function relativeDateLabel(start: string, now: Date = new Date(), end?: string): string {\n const one = (v: string) => {\n const diff = daysFromToday(v, now);\n if (diff === 0) return 'Today';\n if (diff === 1) return 'Tomorrow';\n if (diff === -1) return 'Yesterday';\n return absoluteDateLabel(v);\n };\n return end ? `${one(start)} → ${one(end)}` : one(start);\n}\n\nexport interface DatePreset {\n key: 'today' | 'tomorrow' | 'next_week';\n label: string;\n start: string;\n}\n\n/** The picker's quick dates: Today, Tomorrow, Next week (same weekday, +7 days). */\nexport function datePresets(now: Date = new Date()): DatePreset[] {\n const plus = (days: number) => toLocalISODate(new Date(now.getFullYear(), now.getMonth(), now.getDate() + days));\n return [\n { key: 'today', label: 'Today', start: plus(0) },\n { key: 'tomorrow', label: 'Tomorrow', start: plus(1) },\n { key: 'next_week', label: 'Next week', start: plus(7) },\n ];\n}\n\n/** Avatar letter for a person mention (\"olivia\" → \"O\"; empty → \"?\"). */\nexport function personInitial(name: string): string {\n const ch = name.trim().replace(/^@/, '').charAt(0);\n return ch ? ch.toUpperCase() : '?';\n}\n\n/**\n * Distinct person names used in database rows (`person` properties of `schema`, keyed by\n * property name like `properties.schema`). Values are `[{name}]`, strings or comma lists.\n */\nexport function collectPersonNames(\n schema: Record<string, { type?: string } | undefined> | undefined,\n rows: Array<{ properties?: Record<string, unknown> } | null | undefined>,\n limit = 20,\n): string[] {\n const keys = Object.entries(schema ?? {})\n .filter(([, def]) => def?.type === 'person')\n .map(([name]) => name);\n if (keys.length === 0) return [];\n const seen = new Map<string, string>();\n const add = (v: unknown): void => {\n if (seen.size >= limit || v == null) return;\n if (Array.isArray(v)) {\n v.forEach(add);\n return;\n }\n const name = typeof v === 'object' ? ((v as any).name ?? (v as any).title) : v;\n if (typeof name !== 'string') return;\n for (const part of name.split(',')) {\n const n = part.trim();\n if (n && !seen.has(n.toLowerCase()) && seen.size < limit) seen.set(n.toLowerCase(), n);\n }\n };\n for (const row of rows) {\n const props = row?.properties;\n if (!props) continue;\n for (const k of keys) add(props[k]);\n }\n return Array.from(seen.values());\n}\n"],"names":[],"mappings":"AAQA,MAAM,MAAS,GAAA,CAAC,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,KAAA,EAAO,KAAO,EAAA,KAAA,EAAO,OAAO,KAAK,CAAA;AAElG,MAAM,GAAA,GAAM,CAAC,CAAc,KAAA,MAAA,CAAO,CAAC,CAAE,CAAA,QAAA,CAAS,GAAG,GAAG,CAAA;AAG7C,SAAS,eAAe,CAAiB,EAAA;AAC9C,EAAA,OAAO,GAAG,CAAE,CAAA,WAAA,EAAa,CAAA,CAAA,EAAI,IAAI,CAAE,CAAA,QAAA,EAAa,GAAA,CAAC,CAAC,CAAI,CAAA,EAAA,GAAA,CAAI,CAAE,CAAA,OAAA,EAAS,CAAC,CAAA,CAAA;AACxE;AAGO,SAAS,iBAAiB,KAA4B,EAAA;AAC3D,EAAM,MAAA,GAAA,GAAM,2BAA4B,CAAA,IAAA,CAAK,KAAK,CAAA;AAClD,EAAA,IAAI,KAAY,OAAA,IAAI,KAAK,MAAO,CAAA,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,OAAO,GAAI,CAAA,CAAC,CAAC,CAAI,GAAA,CAAA,EAAG,OAAO,GAAI,CAAA,CAAC,CAAC,CAAC,CAAA;AAC3E,EAAM,MAAA,CAAA,GAAI,IAAK,CAAA,KAAA,CAAM,KAAK,CAAA;AAC1B,EAAA,OAAO,OAAO,KAAM,CAAA,CAAC,IAAI,IAAO,GAAA,IAAI,KAAK,CAAC,CAAA;AAC5C;AAaO,SAAS,kBAAkB,KAAuB,EAAA;AACvD,EAAM,MAAA,CAAA,GAAI,iBAAiB,KAAK,CAAA;AAChC,EAAI,IAAA,CAAC,GAAU,OAAA,KAAA;AACf,EAAA,OAAO,CAAG,EAAA,MAAA,CAAO,CAAE,CAAA,QAAA,EAAU,CAAC,CAAI,CAAA,EAAA,CAAA,CAAE,OAAQ,EAAC,CAAK,EAAA,EAAA,CAAA,CAAE,aAAa,CAAA,CAAA;AACnE;AAoBO,SAAS,WAAY,CAAA,GAAA,mBAAgB,IAAA,IAAA,EAAsB,EAAA;AAChE,EAAA,MAAM,OAAO,CAAC,IAAA,KAAiB,cAAe,CAAA,IAAI,KAAK,GAAI,CAAA,WAAA,EAAe,EAAA,GAAA,CAAI,UAAY,EAAA,GAAA,CAAI,OAAQ,EAAA,GAAI,IAAI,CAAC,CAAA;AAC/G,EAAA,OAAO,CAAC;AAAA,IACN,GAAK,EAAA,OAAA;AAAA,IACL,KAAO,EAAA,OAAA;AAAA,IACP,KAAA,EAAO,KAAK,CAAC;AAAA,GACZ,EAAA;AAAA,IACD,GAAK,EAAA,UAAA;AAAA,IACL,KAAO,EAAA,UAAA;AAAA,IACP,KAAA,EAAO,KAAK,CAAC;AAAA,GACZ,EAAA;AAAA,IACD,GAAK,EAAA,WAAA;AAAA,IACL,KAAO,EAAA,WAAA;AAAA,IACP,KAAA,EAAO,KAAK,CAAC;AAAA,GACd,CAAA;AACH"}