simple-module-pagebuilder 0.0.8__tar.gz → 0.0.10__tar.gz

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 (343) hide show
  1. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/PKG-INFO +1 -1
  2. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/package.json +1 -1
  3. simple_module_pagebuilder-0.0.10/pagebuilder/components/editor/noHeaderActions.tsx +9 -0
  4. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/puckConfig.test.tsx +13 -1
  5. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/puckConfig.tsx +14 -0
  6. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/eyebrow-split-section.tsx +1 -1
  7. simple_module_pagebuilder-0.0.10/pagebuilder/components/widgets/_internal/inline-image.tsx +37 -0
  8. simple_module_pagebuilder-0.0.10/pagebuilder/components/widgets/_internal/markdown-list.tsx +35 -0
  9. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/rich-text.tsx +45 -21
  10. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/faq-render.tsx +10 -8
  11. simple_module_pagebuilder-0.0.10/pagebuilder/components/widgets/markdown-widget.test.tsx +68 -0
  12. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/markdown-widget.tsx +7 -7
  13. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/quote-widget.tsx +20 -3
  14. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/section-intro-widget.tsx +1 -1
  15. simple_module_pagebuilder-0.0.10/pagebuilder/components/widgets/site-header-account.tsx +53 -0
  16. simple_module_pagebuilder-0.0.10/pagebuilder/components/widgets/site-header-widget.test.tsx +89 -0
  17. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/site-header-widget.tsx +26 -2
  18. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/public_views.py +5 -2
  19. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/seo.py +4 -2
  20. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/locales/en.json +5 -1
  21. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/LayoutEditor.tsx +5 -9
  22. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/MediaLibrary.tsx +2 -1
  23. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/PageEditor.tsx +15 -4
  24. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/PageList.tsx +6 -3
  25. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/PendingReview.tsx +2 -1
  26. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/__init__.py +3 -0
  27. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/tenancy.py +26 -0
  28. simple_module_pagebuilder-0.0.10/pagebuilder/utils/markdown.test.ts +65 -0
  29. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/markdown.ts +48 -8
  30. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pyproject.toml +12 -1
  31. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_pages_api.py +25 -0
  32. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_public.py +37 -0
  33. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/.gitignore +0 -0
  34. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/README.md +0 -0
  35. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/__init__.py +0 -0
  36. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/board.py +0 -0
  37. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/boot.py +0 -0
  38. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/ConfirmDialog.tsx +0 -0
  39. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/DiffSummary.tsx +0 -0
  40. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/NewPageDialog.tsx +0 -0
  41. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/NoteDialog.tsx +0 -0
  42. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/PageBoard.tsx +0 -0
  43. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/PageBoardCard.tsx +0 -0
  44. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/PageListFilters.tsx +0 -0
  45. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/PageListRow.tsx +0 -0
  46. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/ScheduledBadge.tsx +0 -0
  47. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/StatusBadge.tsx +0 -0
  48. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/TranslatePageDialog.tsx +0 -0
  49. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blockRegistry.test.ts +0 -0
  50. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blockRegistry.ts +0 -0
  51. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Button.tsx +0 -0
  52. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Columns.tsx +0 -0
  53. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Heading.tsx +0 -0
  54. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Image.test.tsx +0 -0
  55. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Image.tsx +0 -0
  56. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/MediaPicker.tsx +0 -0
  57. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Spacer.tsx +0 -0
  58. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/blocks/Text.tsx +0 -0
  59. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/BlockOutline.tsx +0 -0
  60. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/NarrowCanvas.tsx +0 -0
  61. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/PageActions.tsx +0 -0
  62. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/PageEditorToolbar.tsx +0 -0
  63. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/PageInspectorDrawer.tsx +0 -0
  64. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/PageSettingsPanel.tsx +0 -0
  65. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/RevisionHistoryPanel.tsx +0 -0
  66. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/SchedulePanel.tsx +0 -0
  67. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/SeoPreview.tsx +0 -0
  68. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/SeoSettingsPanel.tsx +0 -0
  69. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/editor/TranslationsPanel.tsx +0 -0
  70. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/layoutPuckConfig.tsx +0 -0
  71. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/lazyBlock.tsx +0 -0
  72. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/localizeConfig.test.ts +0 -0
  73. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/localizeConfig.ts +0 -0
  74. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaFilters.tsx +0 -0
  75. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaFolderSidebar.tsx +0 -0
  76. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaGrid.tsx +0 -0
  77. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaHeader.tsx +0 -0
  78. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaUploadQueue.tsx +0 -0
  79. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/MediaUsageList.tsx +0 -0
  80. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/media/types.ts +0 -0
  81. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/migrateContent.test.ts +0 -0
  82. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/migrateContent.ts +0 -0
  83. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/snapshots/ImportPlanSummary.tsx +0 -0
  84. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/snapshots/SnapshotList.tsx +0 -0
  85. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/snapshots/UploadBundleDialog.tsx +0 -0
  86. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/snapshots/planSummary.test.ts +0 -0
  87. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/snapshots/planSummary.ts +0 -0
  88. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgetCatalog.test.tsx +0 -0
  89. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgetCatalog.ts +0 -0
  90. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/accent-text.tsx +0 -0
  91. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/disclosure-chevron.tsx +0 -0
  92. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/link-arrow.tsx +0 -0
  93. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_internal/solid-icons.tsx +0 -0
  94. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/background-media.tsx +0 -0
  95. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/content-media.tsx +0 -0
  96. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/cta-button.tsx +0 -0
  97. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/empty-placeholder.tsx +0 -0
  98. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/eyebrow-text.tsx +0 -0
  99. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/heading.tsx +0 -0
  100. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/image-srcset.ts +0 -0
  101. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/index.ts +0 -0
  102. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/mask.ts +0 -0
  103. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/section.tsx +0 -0
  104. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/social-icon.tsx +0 -0
  105. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/_shared/text-link.tsx +0 -0
  106. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/accordion-widget.tsx +0 -0
  107. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/alert-widget.tsx +0 -0
  108. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/app-store-badges-widget.tsx +0 -0
  109. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/article-cards-render.tsx +0 -0
  110. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/article-cards-widget.tsx +0 -0
  111. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/call-to-action-render.tsx +0 -0
  112. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/call-to-action-styles.ts +0 -0
  113. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/call-to-action-widget.tsx +0 -0
  114. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/carousel-widget.tsx +0 -0
  115. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/centered-hero-widget.tsx +0 -0
  116. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/colored-action-list-widget.tsx +0 -0
  117. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/column-widget.tsx +0 -0
  118. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/contact-cards-widget.tsx +0 -0
  119. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/contact-form-render.tsx +0 -0
  120. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/contact-form-widget.tsx +0 -0
  121. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/container-widget.tsx +0 -0
  122. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/definition-list-widget.tsx +0 -0
  123. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/divider-widget.test.tsx +0 -0
  124. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/divider-widget.tsx +0 -0
  125. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/eyebrow-section-widget.tsx +0 -0
  126. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/faq-widget.tsx +0 -0
  127. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-card-widget.tsx +0 -0
  128. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-cards-render.tsx +0 -0
  129. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-cards-styles.ts +0 -0
  130. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-cards-widget.tsx +0 -0
  131. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-grid-widget.tsx +0 -0
  132. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/feature-showcase-widget.tsx +0 -0
  133. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/gallery-widget.tsx +0 -0
  134. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/grid-widget.tsx +0 -0
  135. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/hero-widget-props.ts +0 -0
  136. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/hero-widget.tsx +0 -0
  137. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/html-widget.tsx +0 -0
  138. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/iframe-widget.tsx +0 -0
  139. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/leaderboard-widget.tsx +0 -0
  140. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/list-widget.tsx +0 -0
  141. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/logo-cloud-widget.tsx +0 -0
  142. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/media-object-layout.ts +0 -0
  143. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/media-object-render.tsx +0 -0
  144. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/media-object-text.tsx +0 -0
  145. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/media-object-widget.tsx +0 -0
  146. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/newsletter-widget.tsx +0 -0
  147. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/page-header-widget.tsx +0 -0
  148. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/prose-section-widget.tsx +0 -0
  149. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/row-widget.tsx +0 -0
  150. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/signup-banner-widget.tsx +0 -0
  151. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/simple-action-list-widget.tsx +0 -0
  152. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/site-footer-widget.tsx +0 -0
  153. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/site-header-nav.tsx +0 -0
  154. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/social-banner-widget.tsx +0 -0
  155. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/stats-widget.tsx +0 -0
  156. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/steps-widget.tsx +0 -0
  157. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/story-cards-widget.tsx +0 -0
  158. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/table-widget.tsx +0 -0
  159. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/tabs-widget.tsx +0 -0
  160. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/tags-widget.tsx +0 -0
  161. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/testimonial-widget.tsx +0 -0
  162. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/timeline-layout.ts +0 -0
  163. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/timeline-render.tsx +0 -0
  164. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/timeline-widget.tsx +0 -0
  165. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/under-construction-widget.tsx +0 -0
  166. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/video-widget.tsx +0 -0
  167. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/components/widgets/welcome-widget.tsx +0 -0
  168. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/__init__.py +0 -0
  169. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/events.py +0 -0
  170. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/schemas/__init__.py +0 -0
  171. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/schemas/_layout.py +0 -0
  172. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/schemas/_media.py +0 -0
  173. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/schemas/_pages.py +0 -0
  174. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/contracts/schemas/_snapshots.py +0 -0
  175. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/conversion/blocks-to-html.test.ts +0 -0
  176. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/conversion/blocks-to-html.ts +0 -0
  177. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/conversion/index.ts +0 -0
  178. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/conversion/types.ts +0 -0
  179. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/deps.py +0 -0
  180. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/diff.py +0 -0
  181. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/__init__.py +0 -0
  182. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/__init__.py +0 -0
  183. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/_deps.py +0 -0
  184. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/layout.py +0 -0
  185. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/media_detail.py +0 -0
  186. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/pages.py +0 -0
  187. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/revisions.py +0 -0
  188. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/snapshots.py +0 -0
  189. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/uploads.py +0 -0
  190. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/api/workflow.py +0 -0
  191. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/content_views.py +0 -0
  192. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/endpoints/views.py +0 -0
  193. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/checkbox-field.tsx +0 -0
  194. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/file-picker/file-gallery.tsx +0 -0
  195. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/file-picker/image-picker-field.tsx +0 -0
  196. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/file-picker/index.ts +0 -0
  197. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/file-picker/types.ts +0 -0
  198. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/index.ts +0 -0
  199. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/fields/media-adapter.ts +0 -0
  200. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useAutosave.ts +0 -0
  201. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useEditorForm.ts +0 -0
  202. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useIsNarrow.ts +0 -0
  203. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useMediaDetail.ts +0 -0
  204. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useMediaUploads.ts +0 -0
  205. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/usePageRevisions.ts +0 -0
  206. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/usePageSchedule.ts +0 -0
  207. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/usePageWorkflow.ts +0 -0
  208. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/usePendingDialog.ts +0 -0
  209. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/hooks/useSnapshots.ts +0 -0
  210. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/layout_service.py +0 -0
  211. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/locales.py +0 -0
  212. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/media_files.py +0 -0
  213. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/media_images.py +0 -0
  214. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/media_queries.py +0 -0
  215. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/media_service.py +0 -0
  216. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/media_usage.py +0 -0
  217. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/__init__.py +0 -0
  218. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_base.py +0 -0
  219. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_layout.py +0 -0
  220. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_media.py +0 -0
  221. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_page.py +0 -0
  222. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_redirect.py +0 -0
  223. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/models/_snapshot.py +0 -0
  224. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/module.py +0 -0
  225. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/ContentImportReview.tsx +0 -0
  226. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/ContentSnapshots.tsx +0 -0
  227. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/MediaDetail.tsx +0 -0
  228. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/PublicPage.tsx +0 -0
  229. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/pages/Trash.tsx +0 -0
  230. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/permissions.py +0 -0
  231. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/public_claims.py +0 -0
  232. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/py.typed +0 -0
  233. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/redirects.py +0 -0
  234. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/scheduler.py +0 -0
  235. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/security.py +0 -0
  236. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/_common.py +0 -0
  237. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/_revisions.py +0 -0
  238. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/_translations.py +0 -0
  239. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/_trash.py +0 -0
  240. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/service/_workflow.py +0 -0
  241. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/services.py +0 -0
  242. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/settings.py +0 -0
  243. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/__init__.py +0 -0
  244. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/apply.py +0 -0
  245. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/archive.py +0 -0
  246. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/assets.py +0 -0
  247. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/blobs.py +0 -0
  248. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/capture.py +0 -0
  249. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/format.py +0 -0
  250. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/media_match.py +0 -0
  251. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/pages.py +0 -0
  252. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/plan.py +0 -0
  253. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/service.py +0 -0
  254. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/snapshots/validate.py +0 -0
  255. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/static/widgets-base.css +0 -0
  256. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/translation/apply.ts +0 -0
  257. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/translation/extract.ts +0 -0
  258. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/translation/index.ts +0 -0
  259. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/translation/translatable-fields.ts +0 -0
  260. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/translation/translation.test.ts +0 -0
  261. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/api.ts +0 -0
  262. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/blockOutline.test.ts +0 -0
  263. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/blockOutline.ts +0 -0
  264. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/datetime.ts +0 -0
  265. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/decorative-image.ts +0 -0
  266. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/editorSnapshot.ts +0 -0
  267. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/i18n.test.ts +0 -0
  268. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/i18n.ts +0 -0
  269. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/locale.ts +0 -0
  270. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/measure.ts +0 -0
  271. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/mediaApi.ts +0 -0
  272. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/mediaFormat.ts +0 -0
  273. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/pagesApi.ts +0 -0
  274. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/parse-list.ts +0 -0
  275. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/request.test.ts +0 -0
  276. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/request.ts +0 -0
  277. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/slugify.test.ts +0 -0
  278. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/slugify.ts +0 -0
  279. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/snapshotsApi.ts +0 -0
  280. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/types.ts +0 -0
  281. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/pagebuilder/utils/widgetUtils.ts +0 -0
  282. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/conftest.py +0 -0
  283. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/db_fixture.py +0 -0
  284. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/locale_fixture.py +0 -0
  285. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/page_helpers.py +0 -0
  286. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/pg_support.py +0 -0
  287. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/snapshot_fixture.py +0 -0
  288. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/tenant_app.py +0 -0
  289. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/tenant_fixture.py +0 -0
  290. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_admin_list_view.py +0 -0
  291. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_approval_workflow.py +0 -0
  292. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_auth_gating.py +0 -0
  293. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_csrf.py +0 -0
  294. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_draft_preview.py +0 -0
  295. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_hreflang_and_sitemap.py +0 -0
  296. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_i18n.py +0 -0
  297. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_image_processing.py +0 -0
  298. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_media_detail.py +0 -0
  299. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_media_files.py +0 -0
  300. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_media_security.py +0 -0
  301. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_media_usage_escaping.py +0 -0
  302. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_module.py +0 -0
  303. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_multilingual.py +0 -0
  304. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_page_templates.py +0 -0
  305. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_page_translations.py +0 -0
  306. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_pages_search.py +0 -0
  307. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_public_claims.py +0 -0
  308. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_public_routes.py +0 -0
  309. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_public_view_headers.py +0 -0
  310. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_public_viewer.py +0 -0
  311. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_redirects.py +0 -0
  312. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_revision_notes_and_diff.py +0 -0
  313. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_revisions_api.py +0 -0
  314. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_scheduled_publish.py +0 -0
  315. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_scheduler_stop.py +0 -0
  316. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_scheduler_tenancy.py +0 -0
  317. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_seo_meta.py +0 -0
  318. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_settings_source.py +0 -0
  319. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_site_layout.py +0 -0
  320. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_sitemap_robots.py +0 -0
  321. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_apply.py +0 -0
  322. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_apply_media.py +0 -0
  323. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_archive.py +0 -0
  324. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_assets.py +0 -0
  325. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_blobs.py +0 -0
  326. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_capture.py +0 -0
  327. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_media_match.py +0 -0
  328. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_models.py +0 -0
  329. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_multilingual.py +0 -0
  330. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_page_payload.py +0 -0
  331. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_plan.py +0 -0
  332. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_validate.py +0 -0
  333. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshot_views.py +0 -0
  334. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_snapshots_api.py +0 -0
  335. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_blobs.py +0 -0
  336. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_core.py +0 -0
  337. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_isolation.py +0 -0
  338. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_media.py +0 -0
  339. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_tenancy_routes.py +0 -0
  340. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_trash.py +0 -0
  341. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_trash_preconditions.py +0 -0
  342. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tests/test_uploads_api.py +0 -0
  343. {simple_module_pagebuilder-0.0.8 → simple_module_pagebuilder-0.0.10}/tsconfig.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simple_module_pagebuilder
3
- Version: 0.0.8
3
+ Version: 0.0.10
4
4
  Summary: Drag-and-drop visual page builder for simple_module apps
5
5
  Project-URL: Repository, https://github.com/antosubash/simple_module_python_modules
6
6
  Author-email: Anto Subash <antosubash@live.com>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simple-module-py/pagebuilder",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "private": true,
5
5
  "description": "Frontend assets for the PageBuilder module",
6
6
  "peerDependencies": {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Puck `overrides` that drop the header's own "Publish" (#59).
3
+ *
4
+ * Both editors have a toolbar that owns saving and publishing, so Puck's
5
+ * button would be a second, duplicate control. The title, undo/redo and
6
+ * sidebar toggles stay. Module scope so Puck sees a stable object rather than
7
+ * a fresh one on every render.
8
+ */
9
+ export const NO_HEADER_ACTIONS = { headerActions: () => <></> };
@@ -4,7 +4,7 @@ import { translate } from '../utils/i18n';
4
4
  import { type AnyBlock, registerPuckBlocks, resetBlockRegistry } from './blockRegistry';
5
5
  import { getLayoutPuckConfig } from './layoutPuckConfig';
6
6
  import { localizeConfig } from './localizeConfig';
7
- import { getPuckConfig } from './puckConfig';
7
+ import { getPuckConfig, withRootTitle } from './puckConfig';
8
8
 
9
9
  const stub = { render: () => null } as unknown as AnyBlock;
10
10
 
@@ -139,3 +139,15 @@ describe('getLayoutPuckConfig', () => {
139
139
  expect(Object.keys(getLayoutPuckConfig().components)).toContain('Banner');
140
140
  });
141
141
  });
142
+
143
+ describe('withRootTitle', () => {
144
+ it('defaults the root title to the page’s own, not "Untitled page"', () => {
145
+ const config = withRootTitle(getPuckConfig(), 'About us');
146
+ expect(config.root?.defaultProps).toEqual({ title: 'About us', width: 'contained' });
147
+ });
148
+
149
+ it('leaves the config alone when the page has no title yet', () => {
150
+ const base = getPuckConfig();
151
+ expect(withRootTitle(base, null)).toBe(base);
152
+ });
153
+ });
@@ -106,6 +106,20 @@ export function getPuckConfig(): PageConfig {
106
106
  return cachedConfig;
107
107
  }
108
108
 
109
+ /**
110
+ * Seed the root `title` field from the page row (#59).
111
+ *
112
+ * Puck fills a missing root prop from `defaultProps`, so a document saved
113
+ * without `root.props.title` — every seeded one — opened as "Untitled page"
114
+ * even though the page has a title. Defaulting to the page's own title shows
115
+ * the right thing without rewriting a stored document nobody has edited.
116
+ */
117
+ export function withRootTitle(config: PageConfig, title: string | null | undefined): PageConfig {
118
+ if (!title) return config;
119
+ const defaultProps = { ...config.root?.defaultProps, title } as PageRootProps;
120
+ return { ...config, root: { ...config.root, defaultProps } };
121
+ }
122
+
109
123
  export const emptyData = {
110
124
  content: [],
111
125
  root: { props: { title: 'Untitled page', width: 'contained' } },
@@ -54,7 +54,7 @@ export function EyebrowSplitSection({
54
54
  {renderRichText(eyebrow)}
55
55
  </p>
56
56
  )}
57
- <div className="max-w-[var(--pb-split-content-max,none)]">
57
+ <div className="min-w-0 max-w-[var(--pb-split-content-max,none)]">
58
58
  {/* AccentText, not bare renderRichText: this is a display heading on
59
59
  `--pb-display-weight`, where a plain <strong>'s relative `bolder`
60
60
  can compute to no visible change. */}
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ // A link href or image src: ONE level of balanced parentheses, so Wikipedia's
4
+ // `..._(disambiguation)` survives (see LINK_PATTERN in rich-text).
5
+ export const HREF_SOURCE = String.raw`(?:[^\s()]|\([^\s()]*\))+`;
6
+ /** `![alt](src)` — the alt may be empty, as a decorative logo's is. */
7
+ export const IMAGE_SOURCE = String.raw`!\[[^\]]*\]\(${HREF_SOURCE}\)`;
8
+ const IMAGE_EXACT = new RegExp(String.raw`^!\[([^\]]*)\]\((${HREF_SOURCE})\)$`);
9
+
10
+ /**
11
+ * Only http(s) and scheme-less sources (`/media/...`, `logo.png`) load. Editor
12
+ * copy is not fully trusted, so `data:`, `javascript:` and the rest fall
13
+ * through to literal text, the same way an unsafe link href does.
14
+ */
15
+ function isSafeImageSrc(src: string): boolean {
16
+ const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(src);
17
+ return !scheme || ['http', 'https'].includes(scheme[1].toLowerCase());
18
+ }
19
+
20
+ /**
21
+ * `![alt](src)` → `<img>`, or `null` when the text is not exactly one image or
22
+ * its src is unsafe (#66). Inline, so a line of logos sits in a row and a
23
+ * paragraph of its own stacks; `max-w-full` keeps a large one inside the column.
24
+ */
25
+ export function renderInlineImage(markdown: string, key: string): ReactNode | null {
26
+ const match = IMAGE_EXACT.exec(markdown);
27
+ if (!match || !isSafeImageSrc(match[2])) return null;
28
+ return (
29
+ <img
30
+ key={key}
31
+ src={match[2]}
32
+ alt={match[1]}
33
+ loading="lazy"
34
+ className="inline-block h-auto max-w-full align-middle"
35
+ />
36
+ );
37
+ }
@@ -0,0 +1,35 @@
1
+ import type { MarkdownListItem } from '../../../utils/markdown';
2
+ import { renderRichText } from './rich-text';
3
+
4
+ // Nested levels switch to hollow bullets, the way browsers mark a second level.
5
+ // The marker position is inherited explicitly: preflight's `list-style: none`
6
+ // resets it to `outside`, so under the Markdown widget's `list-inside` list
7
+ // the nested markers hung back in line with their parent's.
8
+ const NESTED_CLASS = 'list-[circle] [list-style-position:inherit] pl-5 mt-1 space-y-1';
9
+
10
+ /**
11
+ * A parsed `- ` list, nesting included (#66). The Markdown widget, FAQ answers
12
+ * and widget textareas all render bullets through this, so a nested item can't
13
+ * work in one of them and flatten in another.
14
+ */
15
+ export function MarkdownList({
16
+ items,
17
+ className,
18
+ }: {
19
+ items: MarkdownListItem[];
20
+ className?: string;
21
+ }) {
22
+ return (
23
+ <ul className={className}>
24
+ {items.map((item, i) => (
25
+ // biome-ignore lint/suspicious/noArrayIndexKey: list items are positional slices of the source text
26
+ <li key={i}>
27
+ {renderRichText(item.text)}
28
+ {item.children.length > 0 && (
29
+ <MarkdownList items={item.children} className={NESTED_CLASS} />
30
+ )}
31
+ </li>
32
+ ))}
33
+ </ul>
34
+ );
35
+ }
@@ -5,6 +5,8 @@ import {
5
5
  parseMarkdownBlocks,
6
6
  } from '../../../utils/markdown';
7
7
  import { cn } from '../../../utils/widgetUtils';
8
+ import { HREF_SOURCE, IMAGE_SOURCE, renderInlineImage } from './inline-image';
9
+ import { MarkdownList } from './markdown-list';
8
10
 
9
11
  // `[label](href)`. Split first, so a link's label can still carry the emphasis
10
12
  // markers the inline tokenizer understands ("[**Datenschutz**](/x)").
@@ -15,7 +17,15 @@ import { cn } from '../../../utils/widgetUtils';
15
17
  // leaking the remainder onto the page as stray literal text. Anything the
16
18
  // pattern can't parse falls through unchanged and renders as literal text, so
17
19
  // malformed input is always visible rather than dropped.
18
- const LINK_PATTERN = /(\[[^\]]+\]\((?:[^\s()]|\([^\s()]*\))+\))/g;
20
+ //
21
+ // Images (#66) split out the same way, a linked image `[![alt](src)](href)`
22
+ // first: tried as a plain link, its label would end at the image's own `]`.
23
+ const LINK_PATTERN = new RegExp(
24
+ String.raw`(\[${IMAGE_SOURCE}\]\(${HREF_SOURCE}\)|${IMAGE_SOURCE}|\[[^\]]+\]\(${HREF_SOURCE}\))`,
25
+ 'g',
26
+ );
27
+ const LINKED_IMAGE = new RegExp(String.raw`^\[(${IMAGE_SOURCE})\]\((${HREF_SOURCE})\)$`);
28
+ const LINK = new RegExp(String.raw`^\[([^\]]+)\]\((${HREF_SOURCE})\)$`);
19
29
 
20
30
  // `<strong>`'s UA default `font-weight: bolder` is RELATIVE — inside
21
31
  // `font-light` (300) copy it computes to 400 and the bold is invisible. An
@@ -135,7 +145,18 @@ function renderRichTextNodes(text: string, opts?: RichTextOptions): ReactNode[]
135
145
  for (let i = 0; i < parts.length; i++) {
136
146
  const part = parts[i];
137
147
  if (!part) continue;
138
- const match = /^\[([^\]]+)\]\(((?:[^\s()]|\([^\s()]*\))+)\)$/.exec(part);
148
+ const image = renderInlineImage(part, `i-${i}`);
149
+ if (image) {
150
+ out.push(image);
151
+ continue;
152
+ }
153
+ const linked = LINKED_IMAGE.exec(part);
154
+ const linkedImage = linked && renderInlineImage(linked[1], `i-${i}`);
155
+ if (linked && linkedImage && isSafeHref(linked[2])) {
156
+ out.push(linksAllowed ? anchor(linked[2], linkedImage, `l-${i}`) : linkedImage);
157
+ continue;
158
+ }
159
+ const match = LINK.exec(part);
139
160
  if (match && isSafeHref(match[2])) {
140
161
  const [, label, href] = match;
141
162
  // Inside an `<a>`/`<button>`/`<summary>` an anchor can't be nested, so
@@ -145,19 +166,7 @@ function renderRichTextNodes(text: string, opts?: RichTextOptions): ReactNode[]
145
166
  out.push(...renderEmphasis(label, `u-${i}`, opts));
146
167
  continue;
147
168
  }
148
- // Scheme-relative `//host/...` is off-site too — it must get the
149
- // same new-tab + noopener treatment as absolute http(s) links.
150
- const external = /^(?:https?:)?\/\//.test(href);
151
- out.push(
152
- <a
153
- key={`l-${i}`}
154
- href={href}
155
- className="underline underline-offset-2 text-[color:var(--pb-prose-link-color,inherit)]"
156
- {...(external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
157
- >
158
- {renderEmphasis(label, `l-${i}`, opts)}
159
- </a>,
160
- );
169
+ out.push(anchor(href, renderEmphasis(label, `l-${i}`, opts), `l-${i}`));
161
170
  continue;
162
171
  }
163
172
  out.push(...renderEmphasis(part, `t-${i}`, opts));
@@ -165,6 +174,22 @@ function renderRichTextNodes(text: string, opts?: RichTextOptions): ReactNode[]
165
174
  return out;
166
175
  }
167
176
 
177
+ function anchor(href: string, children: ReactNode, key: string): ReactNode {
178
+ // Scheme-relative `//host/...` is off-site too — it must get the
179
+ // same new-tab + noopener treatment as absolute http(s) links.
180
+ const external = /^(?:https?:)?\/\//.test(href);
181
+ return (
182
+ <a
183
+ key={key}
184
+ href={href}
185
+ className="underline underline-offset-2 text-[color:var(--pb-prose-link-color,inherit)]"
186
+ {...(external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
187
+ >
188
+ {children}
189
+ </a>
190
+ );
191
+ }
192
+
168
193
  export type RichTextBlockProps = {
169
194
  text: string | undefined;
170
195
  className?: string;
@@ -224,12 +249,11 @@ function renderWithSoftBreaks(text: string): ReactNode[] {
224
249
  function renderBlock(block: MarkdownBlock, key: number): ReactNode {
225
250
  if (block.type === 'ul') {
226
251
  return (
227
- <ul key={key} className="list-disc pl-5 [&:not(:first-child)]:mt-3">
228
- {block.items.map((li, j) => (
229
- // biome-ignore lint/suspicious/noArrayIndexKey: list items are positional slices of the source text
230
- <li key={j}>{renderRichText(li)}</li>
231
- ))}
232
- </ul>
252
+ <MarkdownList
253
+ key={key}
254
+ items={block.items}
255
+ className="list-disc pl-5 [&:not(:first-child)]:mt-3"
256
+ />
233
257
  );
234
258
  }
235
259
  return (
@@ -7,6 +7,7 @@ import { parseMarkdownBlocks } from '../../utils/markdown';
7
7
  import { cn } from '../../utils/widgetUtils';
8
8
  import { AccentText } from './_internal/accent-text';
9
9
  import { DisclosureChevron } from './_internal/disclosure-chevron';
10
+ import { MarkdownList } from './_internal/markdown-list';
10
11
  import { RichTextBlock, renderRichText } from './_internal/rich-text';
11
12
  import { eyebrowTextStyle } from './_shared';
12
13
 
@@ -59,13 +60,12 @@ function Answer({ text, inverse }: { text: string; inverse?: boolean }) {
59
60
  >
60
61
  {parseMarkdownBlocks(text || '').map((block, i) =>
61
62
  block.type === 'ul' ? (
62
- // biome-ignore lint/suspicious/noArrayIndexKey: blocks are positional slices of one string, re-derived each render
63
- <ul key={i} className="list-disc pl-5 [&:not(:first-child)]:mt-3">
64
- {block.items.map((li, j) => (
65
- // biome-ignore lint/suspicious/noArrayIndexKey: list items are positional slices too
66
- <li key={j}>{renderRichText(li)}</li>
67
- ))}
68
- </ul>
63
+ <MarkdownList
64
+ // biome-ignore lint/suspicious/noArrayIndexKey: blocks are positional slices of one string, re-derived each render
65
+ key={i}
66
+ items={block.items}
67
+ className="list-disc pl-5 [&:not(:first-child)]:mt-3"
68
+ />
69
69
  ) : (
70
70
  // biome-ignore lint/suspicious/noArrayIndexKey: blocks are positional slices of one string, re-derived each render
71
71
  <p key={i} className="[&:not(:first-child)]:mt-3">
@@ -160,7 +160,9 @@ function SplitFaq({
160
160
  >
161
161
  {renderRichText(eyebrow)}
162
162
  </p>
163
- <div className="max-w-[var(--pb-split-content-max,none)]">
163
+ {/* min-w-0: a grid item's `min-width: auto` let a wide Markdown image
164
+ in an answer push the 2fr track past the coloured band. */}
165
+ <div className="min-w-0 max-w-[var(--pb-split-content-max,none)]">
164
166
  <div className="max-w-[var(--pb-faq-intro-max,none)]">
165
167
  {/* AccentText, not bare renderRichText: these are display headings
166
168
  on `--pb-display-weight`, where a plain <strong>'s relative
@@ -0,0 +1,68 @@
1
+ import type { ReactElement } from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ import { MarkdownWidget } from './markdown-widget';
6
+
7
+ const Markdown = MarkdownWidget.render as unknown as (
8
+ props: Record<string, unknown>,
9
+ ) => ReactElement;
10
+
11
+ function html(content: string): string {
12
+ return renderToStaticMarkup(<Markdown {...MarkdownWidget.defaultProps} content={content} />);
13
+ }
14
+
15
+ // #66: content seeded from existing Markdown (a partners page of logos)
16
+ // rendered `![alt](src)` as literal text and flattened nested lists.
17
+ describe('MarkdownWidget images', () => {
18
+ it('renders an image', () => {
19
+ const out = html('![Acme logo](/media/acme.png)');
20
+ expect(out).toContain('<img');
21
+ expect(out).toContain('src="/media/acme.png"');
22
+ expect(out).toContain('alt="Acme logo"');
23
+ expect(out).not.toContain('![');
24
+ });
25
+
26
+ it('renders a linked image as an image inside the link', () => {
27
+ const out = html('[![Acme](/media/acme.png)](https://acme.example)');
28
+ expect(out).toMatch(
29
+ /<a [^>]*href="https:\/\/acme\.example"[^>]*><img [^>]*src="\/media\/acme\.png"/,
30
+ );
31
+ });
32
+
33
+ it('keeps several images on one line in one paragraph', () => {
34
+ const out = html('![A](/a.png) ![B](https://cdn.example/b.png)');
35
+ expect(out.match(/<img /g)).toHaveLength(2);
36
+ expect(out.match(/<p /g)).toHaveLength(1);
37
+ });
38
+
39
+ it('accepts an empty alt', () => {
40
+ expect(html('![](/logo.png)')).toContain('alt=""');
41
+ });
42
+
43
+ it('leaves an unsafe src as visible text, like an unsafe link', () => {
44
+ for (const src of ['javascript:alert(1)', 'data:image/svg+xml,x']) {
45
+ const out = html(`![x](${src})`);
46
+ expect(out).not.toContain('<img');
47
+ expect(out).toContain(`![x](${src})`);
48
+ }
49
+ });
50
+
51
+ it('does not wrap an image in a link whose href is unsafe', () => {
52
+ const out = html('[![x](/x.png)](javascript:alert(1))');
53
+ expect(out).not.toContain('href="javascript');
54
+ });
55
+
56
+ it('still renders plain links', () => {
57
+ expect(html('[Docs](/docs)')).toMatch(/<a [^>]*href="\/docs"[^>]*>Docs<\/a>/);
58
+ });
59
+ });
60
+
61
+ describe('MarkdownWidget nested lists', () => {
62
+ it('renders an indented bullet as a nested list', () => {
63
+ const out = html('- Partners\n - Gold\n - Silver\n- Press');
64
+ expect(out).toMatch(
65
+ /<li>Partners<ul [^>]*><li>Gold<\/li><li>Silver<\/li><\/ul><\/li><li>Press<\/li>/,
66
+ );
67
+ });
68
+ });
@@ -2,6 +2,7 @@ import type { ComponentConfig } from '@puckeditor/core';
2
2
  import { useMemo } from 'react';
3
3
  import { keys } from '../../utils/i18n';
4
4
  import { parseMarkdownBlocks as renderMarkdown } from '../../utils/markdown';
5
+ import { MarkdownList } from './_internal/markdown-list';
5
6
  import { renderRichText } from './_internal/rich-text';
6
7
 
7
8
  export type MarkdownWidgetProps = {
@@ -128,13 +129,12 @@ function MarkdownRender({ content, width = 'auto', indent = 'none' }: MarkdownWi
128
129
  );
129
130
  if (block.type === 'ul')
130
131
  return (
131
- // biome-ignore lint/suspicious/noArrayIndexKey: author-ordered array with no stable id; content repeats, so a content key collides
132
- <ul key={idx} className="list-disc list-inside space-y-1 mb-4">
133
- {block.items.map((item, i) => (
134
- // biome-ignore lint/suspicious/noArrayIndexKey: author-ordered array with no stable id; content repeats, so a content key collides
135
- <li key={i}>{renderInline(item)}</li>
136
- ))}
137
- </ul>
132
+ <MarkdownList
133
+ // biome-ignore lint/suspicious/noArrayIndexKey: author-ordered array with no stable id; content repeats, so a content key collides
134
+ key={idx}
135
+ items={block.items}
136
+ className="list-disc list-inside space-y-1 mb-4"
137
+ />
138
138
  );
139
139
  return (
140
140
  // biome-ignore lint/suspicious/noArrayIndexKey: author-ordered array with no stable id; content repeats, so a content key collides
@@ -1,4 +1,5 @@
1
1
  import type { ComponentConfig } from '@puckeditor/core';
2
+ import type { CSSProperties } from 'react';
2
3
  import { keys } from '../../utils/i18n';
3
4
  import { cn } from '../../utils/widgetUtils';
4
5
  import { renderRichText } from './_internal/rich-text';
@@ -10,6 +11,18 @@ export type QuoteWidgetProps = {
10
11
  align: 'left' | 'center';
11
12
  };
12
13
 
14
+ // Colours come from the renderer's `--pb-*` tokens rather than a fixed palette,
15
+ // so the quote follows the page's theme whether or not it toggles `.dark` —
16
+ // a dark branded page would otherwise get dark-grey text on its own navy.
17
+ // The tint is mixed from the accent, so it reads on either background.
18
+ const FIGURE_STYLE: CSSProperties = {
19
+ borderColor: 'var(--pb-accent, var(--primary))',
20
+ backgroundColor: 'color-mix(in srgb, var(--pb-accent, var(--primary)) 8%, transparent)',
21
+ };
22
+ const CAPTION_STYLE: CSSProperties = {
23
+ color: 'var(--pb-caption-color, var(--pb-body-color, var(--muted-foreground)))',
24
+ };
25
+
13
26
  export const QuoteWidget: ComponentConfig<QuoteWidgetProps> = {
14
27
  label: keys.pagebuilder.blocks.quote.label,
15
28
  fields: {
@@ -34,15 +47,19 @@ export const QuoteWidget: ComponentConfig<QuoteWidgetProps> = {
34
47
  render: ({ quote, author, source, align }) => (
35
48
  <figure
36
49
  className={cn(
37
- 'max-w-3xl mx-auto px-4 py-10 border-l-4 border-primary-700 bg-primary-50/50 dark:bg-primary-950/30 rounded-r-lg',
50
+ 'max-w-3xl mx-auto px-4 py-10 border-l-4 rounded-r-lg',
38
51
  align === 'center' ? 'text-center' : 'text-left',
39
52
  )}
53
+ style={FIGURE_STYLE}
40
54
  >
41
- <blockquote className="text-xl sm:text-2xl italic text-gray-800 dark:text-gray-100 leading-relaxed">
55
+ <blockquote
56
+ className="text-xl sm:text-2xl italic leading-relaxed"
57
+ style={{ color: 'var(--pb-heading-color, var(--foreground))' }}
58
+ >
42
59
  “{renderRichText(quote)}”
43
60
  </blockquote>
44
61
  {(author || source) && (
45
- <figcaption className="mt-4 text-gray-600 dark:text-gray-400">
62
+ <figcaption className="mt-4" style={CAPTION_STYLE}>
46
63
  {author && <span className="font-semibold">— {renderRichText(author)}</span>}
47
64
  {source && <span className="ml-2 text-sm">({renderRichText(source)})</span>}
48
65
  </figcaption>
@@ -112,7 +112,7 @@ export const SectionIntroWidget: ComponentConfig<SectionIntroWidgetProps> = {
112
112
  {renderRichText(eyebrow)}
113
113
  </p>
114
114
  )}
115
- <div className={eyebrow ? undefined : 'md:col-span-2'}>{content}</div>
115
+ <div className={cn('min-w-0', !eyebrow && 'md:col-span-2')}>{content}</div>
116
116
  </div>
117
117
  </section>
118
118
  );
@@ -0,0 +1,53 @@
1
+ /** Locale switcher and auth-aware CTA for the SiteHeader widget. */
2
+
3
+ import { usePage } from '@inertiajs/react';
4
+ import {
5
+ LocaleSwitcher,
6
+ useHasMultipleLocales,
7
+ } from '@simple-module-py/ui/components/LocaleSwitcher';
8
+
9
+ type AuthSharedProps = {
10
+ auth?: { isAuthenticated?: boolean } | null;
11
+ };
12
+
13
+ /**
14
+ * Whether the visitor has a session, from the `auth` shared prop the framework
15
+ * layouts read. The header only mounts inside an Inertia page; the guard keeps
16
+ * a bare render (a unit test, a static preview) on the anonymous branch rather
17
+ * than throwing, so a header that never set the new props renders as before.
18
+ */
19
+ export function useIsSignedIn(): boolean {
20
+ try {
21
+ // biome-ignore lint/correctness/useHookAtTopLevel: usePage throws outside Inertia, after reading its context, so the hook order is unchanged
22
+ return Boolean(usePage<AuthSharedProps>().props.auth?.isAuthenticated);
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+
28
+ /** The CTA the visitor should see: the signed-in variant only when it is filled in. */
29
+ export function resolveCta(
30
+ signedIn: boolean,
31
+ cta: { label: string; href: string },
32
+ signedInCta: { label?: string; href?: string },
33
+ ): { label: string; href: string } {
34
+ if (signedIn && signedInCta.label) {
35
+ return { label: signedInCta.label, href: signedInCta.href || cta.href };
36
+ }
37
+ return cta;
38
+ }
39
+
40
+ /**
41
+ * The shared switcher, hidden on a single-locale install where it would be an
42
+ * inert pill. It switches the UI locale; it does not jump to a translated
43
+ * page, because the shared control has no hook for a per-page target.
44
+ */
45
+ export function HeaderLocaleSwitcher({ show }: { show: boolean }) {
46
+ const multiple = useHasMultipleLocales();
47
+ if (!show || !multiple) return null;
48
+ return (
49
+ <div className="ml-auto mr-2 flex items-center lg:ml-0 lg:mr-0">
50
+ <LocaleSwitcher />
51
+ </div>
52
+ );
53
+ }
@@ -0,0 +1,89 @@
1
+ // @vitest-environment happy-dom
2
+ import * as React from 'react';
3
+ import { renderToStaticMarkup } from 'react-dom/server';
4
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+
6
+ let shared: Record<string, unknown> = {};
7
+ vi.mock('@inertiajs/react', () => ({
8
+ usePage: () => ({ props: shared }),
9
+ }));
10
+
11
+ // The framework ui package ships JSX sources compiled with the classic runtime
12
+ // under vitest, so its components expect a global React.
13
+ (globalThis as { React?: unknown }).React = React;
14
+
15
+ import type { SiteHeaderWidgetProps } from './site-header-widget';
16
+
17
+ const { SiteHeaderRender, SiteHeaderWidget } = await import('./site-header-widget');
18
+ const { resolveCta } = await import('./site-header-account');
19
+
20
+ const base: Record<string, unknown> = {
21
+ ...(SiteHeaderWidget.defaultProps as object),
22
+ ctaLabel: 'Sign in',
23
+ ctaHref: '/users/login',
24
+ };
25
+ const i18n = (supportedLocales: string[]) => ({
26
+ locale: 'en',
27
+ supportedLocales,
28
+ messages: {},
29
+ });
30
+ const render = (props: Record<string, unknown> = {}) =>
31
+ renderToStaticMarkup(
32
+ <SiteHeaderRender {...({ ...base, ...props } as unknown as SiteHeaderWidgetProps)} />,
33
+ );
34
+
35
+ beforeEach(() => {
36
+ shared = { auth: { isAuthenticated: false }, i18n: i18n(['en', 'fr']) };
37
+ });
38
+
39
+ describe('SiteHeader locale switcher', () => {
40
+ it('is hidden unless showLocaleSwitcher is set', () => {
41
+ expect(render()).not.toContain('/i18n/set-locale');
42
+ });
43
+
44
+ it('renders the shared switcher when enabled on a multi-locale install', () => {
45
+ const out = render({ showLocaleSwitcher: true });
46
+ expect(out).toContain('/i18n/set-locale');
47
+ expect(out).toContain('>EN<');
48
+ });
49
+
50
+ it('stays hidden on a single-locale install', () => {
51
+ shared = { auth: {}, i18n: i18n(['en']) };
52
+ expect(render({ showLocaleSwitcher: true })).not.toContain('>EN<');
53
+ });
54
+
55
+ it('exposes the toggle as an editor field defaulting to off', () => {
56
+ expect(SiteHeaderWidget.fields).toHaveProperty('showLocaleSwitcher');
57
+ expect(SiteHeaderWidget.defaultProps?.showLocaleSwitcher).toBe(false);
58
+ });
59
+ });
60
+
61
+ describe('SiteHeader auth-aware CTA', () => {
62
+ const props = { signedInLabel: 'Dashboard', signedInHref: '/dashboard/' };
63
+
64
+ it('shows the anonymous CTA to a visitor', () => {
65
+ const out = render(props);
66
+ expect(out).toContain('Sign in');
67
+ expect(out).not.toContain('Dashboard');
68
+ });
69
+
70
+ it('switches to the signed-in label and link with a session', () => {
71
+ shared = { auth: { isAuthenticated: true } };
72
+ const out = render(props);
73
+ expect(out).toContain('Dashboard');
74
+ expect(out).toContain('href="/dashboard/"');
75
+ expect(out).not.toContain('>Sign in<');
76
+ });
77
+
78
+ it('keeps the CTA for a signed-in visitor when no signed-in label is set', () => {
79
+ shared = { auth: { isAuthenticated: true } };
80
+ expect(render()).toContain('>Sign in<');
81
+ });
82
+
83
+ it('falls back to the CTA link when only the label is set', () => {
84
+ expect(resolveCta(true, { label: 'Sign in', href: '/x' }, { label: 'Hi', href: '' })).toEqual({
85
+ label: 'Hi',
86
+ href: '/x',
87
+ });
88
+ });
89
+ });