@rynt/sdk 0.9.53

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 (332) hide show
  1. package/README.md +122 -0
  2. package/REGISTRIES.md +189 -0
  3. package/env.d.ts +11 -0
  4. package/host-shims.d.ts +30 -0
  5. package/package.json +88 -0
  6. package/src/extension-marketplace/api-types.ts +141 -0
  7. package/src/extension-marketplace/client.ts +296 -0
  8. package/src/extension-marketplace/index.ts +22 -0
  9. package/src/extension-marketplace/schemas.ts +178 -0
  10. package/src/extensions/ExtensionRoutePage.vue +17 -0
  11. package/src/extensions/context.ts +37 -0
  12. package/src/extensions/disabled-folder.ts +21 -0
  13. package/src/extensions/extension-expose-map.ts +5 -0
  14. package/src/extensions/extension-expose.ts +48 -0
  15. package/src/extensions/graph.ts +67 -0
  16. package/src/extensions/index.ts +251 -0
  17. package/src/extensions/invite-handler/types.ts +20 -0
  18. package/src/extensions/launcher-entities/create-launcher-entity.ts +25 -0
  19. package/src/extensions/launcher-entities/keys.ts +46 -0
  20. package/src/extensions/launcher-entities/launcher-entity-components.ts +177 -0
  21. package/src/extensions/launcher-entities/props-map.ts +69 -0
  22. package/src/extensions/launcher-entities/registry.ts +32 -0
  23. package/src/extensions/launcher-models/apis/accounts-contracts.ts +102 -0
  24. package/src/extensions/launcher-models/apis/launcher-model-apis.ts +553 -0
  25. package/src/extensions/launcher-models/keys.ts +23 -0
  26. package/src/extensions/launcher-models/public.ts +9 -0
  27. package/src/extensions/launcher-models/registry-core.ts +34 -0
  28. package/src/extensions/manifest-types.ts +22 -0
  29. package/src/extensions/manifest.ts +46 -0
  30. package/src/extensions/marketplace-open-key.ts +26 -0
  31. package/src/extensions/plugin-types.ts +44 -0
  32. package/src/extensions/plugin.ts +62 -0
  33. package/src/extensions/registries/bootstrap.ts +11 -0
  34. package/src/extensions/registries/builtins/account-provider.ts +6 -0
  35. package/src/extensions/registries/builtins/app-topbar-left-widgets.ts +6 -0
  36. package/src/extensions/registries/builtins/app-topbar-right-widgets.ts +6 -0
  37. package/src/extensions/registries/builtins/app-topbar-status-widgets.ts +6 -0
  38. package/src/extensions/registries/builtins/build-card-actions.ts +6 -0
  39. package/src/extensions/registries/builtins/build-card-after-meta.ts +6 -0
  40. package/src/extensions/registries/builtins/build-card-before-media.ts +6 -0
  41. package/src/extensions/registries/builtins/build-card-before-meta.ts +6 -0
  42. package/src/extensions/registries/builtins/build-card-footer-actions.ts +6 -0
  43. package/src/extensions/registries/builtins/build-detail-after-content.ts +6 -0
  44. package/src/extensions/registries/builtins/build-detail-before-content.ts +6 -0
  45. package/src/extensions/registries/builtins/build-detail-before-hero.ts +6 -0
  46. package/src/extensions/registries/builtins/build-detail-header-actions.ts +6 -0
  47. package/src/extensions/registries/builtins/build-detail-mod-row-actions.ts +6 -0
  48. package/src/extensions/registries/builtins/build-detail-resourcepack-row-actions.ts +6 -0
  49. package/src/extensions/registries/builtins/build-detail-right-column-bottom.ts +6 -0
  50. package/src/extensions/registries/builtins/build-detail-right-column-top.ts +6 -0
  51. package/src/extensions/registries/builtins/dialog-footer-actions.ts +6 -0
  52. package/src/extensions/registries/builtins/feed-after-content.ts +6 -0
  53. package/src/extensions/registries/builtins/feed-before-content.ts +6 -0
  54. package/src/extensions/registries/builtins/file-editor.ts +19 -0
  55. package/src/extensions/registries/builtins/friends-after-list.ts +6 -0
  56. package/src/extensions/registries/builtins/friends-before-list.ts +6 -0
  57. package/src/extensions/registries/builtins/index.ts +141 -0
  58. package/src/extensions/registries/builtins/invite-handler.ts +7 -0
  59. package/src/extensions/registries/builtins/library-after-content.ts +6 -0
  60. package/src/extensions/registries/builtins/library-before-content.ts +6 -0
  61. package/src/extensions/registries/builtins/loader.ts +8 -0
  62. package/src/extensions/registries/builtins/map-card-actions.ts +6 -0
  63. package/src/extensions/registries/builtins/map-card-after-meta.ts +6 -0
  64. package/src/extensions/registries/builtins/map-card-before-meta.ts +6 -0
  65. package/src/extensions/registries/builtins/map-card-footer-actions.ts +6 -0
  66. package/src/extensions/registries/builtins/map-detail-after-content.ts +6 -0
  67. package/src/extensions/registries/builtins/map-detail-before-content.ts +6 -0
  68. package/src/extensions/registries/builtins/map-detail-header-actions.ts +6 -0
  69. package/src/extensions/registries/builtins/markdown-editor-tiptap-extensions.ts +7 -0
  70. package/src/extensions/registries/builtins/markdown-editor-toolbar-actions.ts +6 -0
  71. package/src/extensions/registries/builtins/markdown-renderer-after-content.ts +6 -0
  72. package/src/extensions/registries/builtins/markdown-renderer-before-content.ts +6 -0
  73. package/src/extensions/registries/builtins/mod-details-footer-actions.ts +6 -0
  74. package/src/extensions/registries/builtins/mod-manage-actions.ts +6 -0
  75. package/src/extensions/registries/builtins/mod-provider.ts +5 -0
  76. package/src/extensions/registries/builtins/nav.ts +7 -0
  77. package/src/extensions/registries/builtins/page.ts +13 -0
  78. package/src/extensions/registries/builtins/projects-after-content.ts +6 -0
  79. package/src/extensions/registries/builtins/projects-before-content.ts +6 -0
  80. package/src/extensions/registries/builtins/resourcepack-manage-actions.ts +7 -0
  81. package/src/extensions/registries/builtins/server-card-actions.ts +6 -0
  82. package/src/extensions/registries/builtins/server-card-after-meta.ts +6 -0
  83. package/src/extensions/registries/builtins/server-card-before-meta.ts +6 -0
  84. package/src/extensions/registries/builtins/server-card-footer-actions.ts +6 -0
  85. package/src/extensions/registries/builtins/server-detail-after-content.ts +6 -0
  86. package/src/extensions/registries/builtins/server-detail-before-content.ts +6 -0
  87. package/src/extensions/registries/builtins/server-detail-header-actions.ts +6 -0
  88. package/src/extensions/registries/builtins/settings-after-sections.ts +6 -0
  89. package/src/extensions/registries/builtins/settings-before-sections.ts +6 -0
  90. package/src/extensions/registries/builtins/settings-section-widgets.ts +6 -0
  91. package/src/extensions/registries/builtins/shaderpack-manage-actions.ts +7 -0
  92. package/src/extensions/registries/builtins/shell.ts +5 -0
  93. package/src/extensions/registries/builtins/sidebar-after-content.ts +6 -0
  94. package/src/extensions/registries/builtins/sidebar-before-content.ts +6 -0
  95. package/src/extensions/registries/builtins/sidebar-footer-widgets.ts +6 -0
  96. package/src/extensions/registries/builtins/sidebar-header-widgets.ts +6 -0
  97. package/src/extensions/registries/builtins/sidebar.ts +11 -0
  98. package/src/extensions/registries/builtins/theme.ts +5 -0
  99. package/src/extensions/registries/builtins/user-card-after-meta.ts +6 -0
  100. package/src/extensions/registries/builtins/user-card-before-meta.ts +6 -0
  101. package/src/extensions/registries/builtins/user-menu-actions.ts +6 -0
  102. package/src/extensions/registries/builtins/user-menu-after-actions.ts +6 -0
  103. package/src/extensions/registries/builtins/user-menu-before-actions.ts +6 -0
  104. package/src/extensions/registries/builtins/user-strip.ts +5 -0
  105. package/src/extensions/registries/clear-extension-ui-registries.ts +15 -0
  106. package/src/extensions/registries/define-extension-registry.ts +58 -0
  107. package/src/extensions/registries/extension-host-api.ts +41 -0
  108. package/src/extensions/registries/extension-registry-api.ts +103 -0
  109. package/src/extensions/registries/extension-registry-payload-map.ts +9 -0
  110. package/src/extensions/registries/extension-scope.ts +41 -0
  111. package/src/extensions/registries/get-registry.ts +23 -0
  112. package/src/extensions/registries/index.ts +58 -0
  113. package/src/extensions/registries/manifest-rynt.ts +193 -0
  114. package/src/extensions/registries/registry-slot.ts +40 -0
  115. package/src/extensions/registries/registry-value-map.ts +89 -0
  116. package/src/extensions/registries/store.ts +206 -0
  117. package/src/extensions/resolve-extensions.ts +245 -0
  118. package/src/extensions/router-bridge.ts +103 -0
  119. package/src/extensions/session.ts +6 -0
  120. package/src/extensions/slug.ts +23 -0
  121. package/src/extensions/version.ts +147 -0
  122. package/src/host/extensions-composables.ts +33 -0
  123. package/src/host/extensions-init.ts +194 -0
  124. package/src/host/index.ts +11 -0
  125. package/src/host/launcher-models/index.ts +4 -0
  126. package/src/index.ts +229 -0
  127. package/src/minecraft-loader/base-loader.ts +102 -0
  128. package/src/minecraft-loader/index.ts +11 -0
  129. package/src/minecraft-loader/loader-registry.ts +72 -0
  130. package/src/shared/api/assets.ts +112 -0
  131. package/src/shared/api/auth.ts +283 -0
  132. package/src/shared/api/builds.ts +647 -0
  133. package/src/shared/api/config.ts +19 -0
  134. package/src/shared/api/download-stats.ts +103 -0
  135. package/src/shared/api/downloads.ts +36 -0
  136. package/src/shared/api/entity-authorship.ts +60 -0
  137. package/src/shared/api/events.ts +393 -0
  138. package/src/shared/api/friends.ts +140 -0
  139. package/src/shared/api/graphql.ts +87 -0
  140. package/src/shared/api/index.ts +23 -0
  141. package/src/shared/api/invites.ts +262 -0
  142. package/src/shared/api/library.ts +44 -0
  143. package/src/shared/api/maps.ts +385 -0
  144. package/src/shared/api/notify-websocket.ts +140 -0
  145. package/src/shared/api/posts.ts +357 -0
  146. package/src/shared/api/projectServers.ts +379 -0
  147. package/src/shared/api/serverMembers.ts +173 -0
  148. package/src/shared/api/users.ts +294 -0
  149. package/src/shared/composables/buildEditor/useBuildEditor.ts +66 -0
  150. package/src/shared/composables/buildManifest/buildManifest.ts +447 -0
  151. package/src/shared/composables/filesEditor/filesEditor.ts +346 -0
  152. package/src/shared/composables/index.ts +10 -0
  153. package/src/shared/composables/modsEditor/modsEditor.ts +1678 -0
  154. package/src/shared/composables/registrySlot/registry-slot-utils.ts +25 -0
  155. package/src/shared/composables/registrySlot/useRegistrySlotMissing.ts +35 -0
  156. package/src/shared/composables/resourcePacksEditor/resourcePacksEditor.ts +448 -0
  157. package/src/shared/composables/shaderPacksEditor/shaderPacksEditor.ts +395 -0
  158. package/src/shared/composables/useSkinRender.ts +70 -0
  159. package/src/shared/composables/useZlDeepLink.ts +178 -0
  160. package/src/shared/definitions/defineGraphCache.ts +216 -0
  161. package/src/shared/definitions/defineStore.ts +32 -0
  162. package/src/shared/definitions/index.ts +2 -0
  163. package/src/shared/minecraft-types/build-manifest.ts +611 -0
  164. package/src/shared/minecraft-types/index.ts +3 -0
  165. package/src/shared/minecraft-types/launcher-versions.ts +32 -0
  166. package/src/shared/minecraft-types/minecraft-launcher-types.ts +276 -0
  167. package/src/shared/mocks/index.ts +1 -0
  168. package/src/shared/mocks/navigation.ts +17 -0
  169. package/src/shared/mods/http.ts +45 -0
  170. package/src/shared/mods/index.ts +5 -0
  171. package/src/shared/mods/marketplace-editor-search.ts +266 -0
  172. package/src/shared/mods/marketplace-search-utils.ts +42 -0
  173. package/src/shared/mods/mod-marketplace-registry.ts +66 -0
  174. package/src/shared/mods/mod-marketplace-types.ts +28 -0
  175. package/src/shared/mods/providers/curseforge.ts +464 -0
  176. package/src/shared/mods/providers/index.ts +8 -0
  177. package/src/shared/mods/providers/modrinth.ts +402 -0
  178. package/src/shared/mods/resolve-mods-provider-loader-ids.ts +77 -0
  179. package/src/shared/mods/types.ts +76 -0
  180. package/src/shared/styles/index.css +713 -0
  181. package/src/shared/themes/index.ts +23 -0
  182. package/src/shared/themes/theme-tokens-black.json +126 -0
  183. package/src/shared/themes/theme-tokens-classic.json +126 -0
  184. package/src/shared/themes/theme-tokens-pink.json +126 -0
  185. package/src/shared/themes/theme-tokens.json +126 -0
  186. package/src/shared/themes/types.ts +85 -0
  187. package/src/shared/types/API_DOCUMENTATION.md +422 -0
  188. package/src/shared/types/account.ts +40 -0
  189. package/src/shared/types/build.ts +8 -0
  190. package/src/shared/types/entities.ts +181 -0
  191. package/src/shared/types/index.ts +6 -0
  192. package/src/shared/types/invite-payloads.ts +60 -0
  193. package/src/shared/types/navigation.ts +16 -0
  194. package/src/shared/types/running-build.ts +51 -0
  195. package/src/shared/types/serverMember.ts +17 -0
  196. package/src/shared/types/user.ts +55 -0
  197. package/src/shared/ui/base/Avatar.vue +262 -0
  198. package/src/shared/ui/base/Badge.vue +47 -0
  199. package/src/shared/ui/base/Button.vue +78 -0
  200. package/src/shared/ui/base/Divider.vue +42 -0
  201. package/src/shared/ui/base/Icon.vue +597 -0
  202. package/src/shared/ui/base/StatusIndicator.vue +44 -0
  203. package/src/shared/ui/base/index.ts +7 -0
  204. package/src/shared/ui/cards/InviteCard.vue +47 -0
  205. package/src/shared/ui/cards/index.ts +2 -0
  206. package/src/shared/ui/dialog/Dialog.vue +71 -0
  207. package/src/shared/ui/dialog/DialogContent.vue +31 -0
  208. package/src/shared/ui/dialog/DialogFooter.vue +14 -0
  209. package/src/shared/ui/dialog/DialogHeader.vue +41 -0
  210. package/src/shared/ui/dialog/index.ts +5 -0
  211. package/src/shared/ui/editors/AttachmentImagesEditor.vue +133 -0
  212. package/src/shared/ui/editors/ContentAttachmentsDisplay.vue +76 -0
  213. package/src/shared/ui/editors/MarkdownEditor.vue +956 -0
  214. package/src/shared/ui/editors/MarkdownRenderer.vue +299 -0
  215. package/src/shared/ui/editors/RichContentImageViewer.vue +85 -0
  216. package/src/shared/ui/editors/SocialPostMediaZone.vue +320 -0
  217. package/src/shared/ui/editors/index.ts +6 -0
  218. package/src/shared/ui/editors/markdown-editor-gallery.ts +234 -0
  219. package/src/shared/ui/editors/markdown-editor-image.ts +178 -0
  220. package/src/shared/ui/form/Checkbox.vue +38 -0
  221. package/src/shared/ui/form/FormField.vue +30 -0
  222. package/src/shared/ui/form/FormGrid.vue +38 -0
  223. package/src/shared/ui/form/ImageEditor.vue +598 -0
  224. package/src/shared/ui/form/Input.vue +72 -0
  225. package/src/shared/ui/form/Range.vue +65 -0
  226. package/src/shared/ui/form/Select.vue +76 -0
  227. package/src/shared/ui/form/Switch.vue +38 -0
  228. package/src/shared/ui/form/Textarea.vue +144 -0
  229. package/src/shared/ui/form/index.ts +9 -0
  230. package/src/shared/ui/index.ts +9 -0
  231. package/src/shared/ui/layout/BusyOverlay.vue +31 -0
  232. package/src/shared/ui/layout/Callout.vue +44 -0
  233. package/src/shared/ui/layout/Card.vue +38 -0
  234. package/src/shared/ui/layout/Container.vue +36 -0
  235. package/src/shared/ui/layout/EmptyState.vue +99 -0
  236. package/src/shared/ui/layout/EntityMediaRow.vue +54 -0
  237. package/src/shared/ui/layout/FilterResultsLayout.vue +22 -0
  238. package/src/shared/ui/layout/FloatingPanel.vue +37 -0
  239. package/src/shared/ui/layout/FullscreenDimmer.vue +11 -0
  240. package/src/shared/ui/layout/Grid.vue +40 -0
  241. package/src/shared/ui/layout/Inline.vue +59 -0
  242. package/src/shared/ui/layout/LoadingState.vue +39 -0
  243. package/src/shared/ui/layout/MediaBox.vue +47 -0
  244. package/src/shared/ui/layout/OverlayPanel.vue +28 -0
  245. package/src/shared/ui/layout/OverlayWaitPanel.vue +22 -0
  246. package/src/shared/ui/layout/PageSection.vue +43 -0
  247. package/src/shared/ui/layout/PageToolbar.vue +29 -0
  248. package/src/shared/ui/layout/Panel.vue +39 -0
  249. package/src/shared/ui/layout/ProgressBar.vue +49 -0
  250. package/src/shared/ui/layout/Section.vue +30 -0
  251. package/src/shared/ui/layout/SegmentedControl.vue +43 -0
  252. package/src/shared/ui/layout/SelectableCard.vue +46 -0
  253. package/src/shared/ui/layout/SelectableRow.vue +41 -0
  254. package/src/shared/ui/layout/Skeleton.vue +25 -0
  255. package/src/shared/ui/layout/SkeletonAvatar.vue +30 -0
  256. package/src/shared/ui/layout/SkeletonEntityCard.vue +20 -0
  257. package/src/shared/ui/layout/SkeletonFeedPost.vue +22 -0
  258. package/src/shared/ui/layout/SkeletonGrid.vue +18 -0
  259. package/src/shared/ui/layout/SkeletonListRow.vue +31 -0
  260. package/src/shared/ui/layout/SkeletonText.vue +25 -0
  261. package/src/shared/ui/layout/Stack.vue +42 -0
  262. package/src/shared/ui/layout/StateBlock.vue +44 -0
  263. package/src/shared/ui/layout/TwoPaneLayout.vue +35 -0
  264. package/src/shared/ui/layout/VirtualList.vue +160 -0
  265. package/src/shared/ui/layout/index.ts +35 -0
  266. package/src/shared/ui/layout/skeletonSurfaceStyles.ts +24 -0
  267. package/src/shared/ui/navigation/NavItem.vue +139 -0
  268. package/src/shared/ui/navigation/Tab.vue +61 -0
  269. package/src/shared/ui/navigation/Tabs.vue +37 -0
  270. package/src/shared/ui/navigation/index.ts +4 -0
  271. package/src/shared/ui/primitives/Action.vue +19 -0
  272. package/src/shared/ui/primitives/Block.vue +28 -0
  273. package/src/shared/ui/primitives/CanvasView.vue +19 -0
  274. package/src/shared/ui/primitives/Control.vue +24 -0
  275. package/src/shared/ui/primitives/ControlSelect.vue +19 -0
  276. package/src/shared/ui/primitives/ControlTextarea.vue +17 -0
  277. package/src/shared/ui/primitives/FieldLabel.vue +19 -0
  278. package/src/shared/ui/primitives/Form.vue +19 -0
  279. package/src/shared/ui/primitives/Heading.vue +29 -0
  280. package/src/shared/ui/primitives/Image.vue +17 -0
  281. package/src/shared/ui/primitives/LineBreak.vue +3 -0
  282. package/src/shared/ui/primitives/Link.vue +19 -0
  283. package/src/shared/ui/primitives/List.vue +28 -0
  284. package/src/shared/ui/primitives/ListItem.vue +19 -0
  285. package/src/shared/ui/primitives/OptionItem.vue +19 -0
  286. package/src/shared/ui/primitives/Text.vue +28 -0
  287. package/src/shared/ui/primitives/VideoView.vue +19 -0
  288. package/src/shared/ui/primitives/index.ts +19 -0
  289. package/src/shared/ui/primitives/resolveElement.ts +25 -0
  290. package/src/shared/ui/special/AngularAccent.vue +106 -0
  291. package/src/shared/ui/special/ExtensionRegistrySlotButton.vue +143 -0
  292. package/src/shared/ui/special/InfoRow.vue +39 -0
  293. package/src/shared/ui/special/LogViewer.vue +53 -0
  294. package/src/shared/ui/special/PageHeader.vue +23 -0
  295. package/src/shared/ui/special/RegistrySlotMissingCallout.vue +48 -0
  296. package/src/shared/ui/special/WelcomeCard.vue +32 -0
  297. package/src/shared/ui/special/index.ts +9 -0
  298. package/src/shared/utils/app-paths.ts +50 -0
  299. package/src/shared/utils/attachments.ts +16 -0
  300. package/src/shared/utils/autostart.ts +213 -0
  301. package/src/shared/utils/build-files.ts +439 -0
  302. package/src/shared/utils/build-manifest-init.ts +176 -0
  303. package/src/shared/utils/cloudinary.ts +67 -0
  304. package/src/shared/utils/cn.ts +7 -0
  305. package/src/shared/utils/download-stats-week.ts +165 -0
  306. package/src/shared/utils/entity-api-to-cache.ts +84 -0
  307. package/src/shared/utils/entity-build-from-api.ts +1 -0
  308. package/src/shared/utils/entity-display.ts +27 -0
  309. package/src/shared/utils/entity-map-from-api.ts +1 -0
  310. package/src/shared/utils/file-hash.ts +65 -0
  311. package/src/shared/utils/formatSize.ts +5 -0
  312. package/src/shared/utils/formatTime.ts +157 -0
  313. package/src/shared/utils/getAccountSkinRender.ts +32 -0
  314. package/src/shared/utils/index.ts +34 -0
  315. package/src/shared/utils/local-mods.ts +678 -0
  316. package/src/shared/utils/local-settings.ts +217 -0
  317. package/src/shared/utils/member-join-stats.ts +35 -0
  318. package/src/shared/utils/platform.ts +86 -0
  319. package/src/shared/utils/play-host-slug.ts +92 -0
  320. package/src/shared/utils/rich-content.ts +294 -0
  321. package/src/shared/utils/safeRequest.ts +23 -0
  322. package/src/shared/utils/semver.ts +81 -0
  323. package/src/shared/utils/serverPermissions.ts +155 -0
  324. package/src/shared/utils/skin-render-cache.ts +372 -0
  325. package/src/shared/utils/stripMarkdown.ts +45 -0
  326. package/src/shared/utils/transliterate.ts +74 -0
  327. package/src/shared/utils/updateAccountSkinRender.ts +64 -0
  328. package/src/shared/utils/updater.ts +218 -0
  329. package/src/shared/utils/uploadImage.ts +195 -0
  330. package/src/shared/utils/user-status.ts +9 -0
  331. package/src/tiptap/index.ts +7 -0
  332. package/tsconfig.json +13 -0
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <Block
3
+ class="overflow-hidden rounded p-3"
4
+ :style="skeletonCardStyle"
5
+ aria-hidden="true"
6
+ >
7
+ <Skeleton class="mb-3 aspect-video w-full rounded" />
8
+ <Skeleton class="mb-2 h-4 w-3/4 max-w-[200px]" />
9
+ <Skeleton class="mb-1.5 h-3 w-full" />
10
+ <Skeleton class="h-3 w-2/3 max-w-[160px]" />
11
+ </Block>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import Block from '../primitives/Block.vue';
16
+ import Skeleton from './Skeleton.vue';
17
+ import { skeletonPanelShellStyle } from './skeletonSurfaceStyles';
18
+
19
+ const skeletonCardStyle = skeletonPanelShellStyle('25%', '14%');
20
+ </script>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <Block
3
+ class="overflow-hidden rounded"
4
+ :style="skeletonPostShellStyle"
5
+ aria-hidden="true"
6
+ >
7
+ <Skeleton class="aspect-[21/9] w-full max-h-36 rounded" />
8
+ <Block class="space-y-2 p-3">
9
+ <Skeleton class="h-4 w-[80%] max-w-[280px]" />
10
+ <Skeleton class="h-3 w-full" />
11
+ <Skeleton class="h-3 w-3/5 max-w-[200px]" />
12
+ </Block>
13
+ </Block>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import Block from '../primitives/Block.vue';
18
+ import Skeleton from './Skeleton.vue';
19
+ import { skeletonPanelShellStyle } from './skeletonSurfaceStyles';
20
+
21
+ const skeletonPostShellStyle = skeletonPanelShellStyle('20%', '14%');
22
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <Grid :cols="cols" gap="sm" class="!gap-3">
3
+ <SkeletonEntityCard v-for="i in count" :key="i" />
4
+ </Grid>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import Grid from './Grid.vue';
9
+ import SkeletonEntityCard from './SkeletonEntityCard.vue';
10
+
11
+ withDefaults(
12
+ defineProps<{
13
+ count?: number;
14
+ cols?: 1 | 2 | 3 | 4;
15
+ }>(),
16
+ { count: 8, cols: 3 },
17
+ );
18
+ </script>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <Inline
3
+ class="w-full items-center gap-3 rounded-md px-3 py-2.5"
4
+ gap="md"
5
+ :style="skeletonRowShellStyle"
6
+ aria-hidden="true"
7
+ >
8
+ <SkeletonAvatar :size="avatarSize" />
9
+ <Block class="min-w-0 flex-1 space-y-2">
10
+ <Skeleton class="h-3.5 w-[45%] max-w-[200px]" />
11
+ <Skeleton class="h-3 w-[70%] max-w-[260px]" />
12
+ </Block>
13
+ </Inline>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import Block from '../primitives/Block.vue';
18
+ import Inline from './Inline.vue';
19
+ import Skeleton from './Skeleton.vue';
20
+ import SkeletonAvatar from './SkeletonAvatar.vue';
21
+ import { skeletonPanelShellStyle } from './skeletonSurfaceStyles';
22
+
23
+ const skeletonRowShellStyle = skeletonPanelShellStyle('20%', '12%');
24
+
25
+ withDefaults(
26
+ defineProps<{
27
+ avatarSize?: 'sm' | 'md' | 'lg';
28
+ }>(),
29
+ { avatarSize: 'md' },
30
+ );
31
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <Block class="w-full space-y-2" aria-hidden="true">
3
+ <Skeleton
4
+ v-for="line in lines"
5
+ :key="line"
6
+ :class="cn('h-3.5', line === lines && lines > 1 ? 'max-w-[55%]' : 'w-full')"
7
+ />
8
+ </Block>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { computed } from 'vue';
13
+ import { cn } from '../../utils/cn';
14
+ import Block from '../primitives/Block.vue';
15
+ import Skeleton from './Skeleton.vue';
16
+
17
+ const props = withDefaults(
18
+ defineProps<{
19
+ lines?: 1 | 2 | 3;
20
+ }>(),
21
+ { lines: 2 },
22
+ );
23
+
24
+ const lines = computed(() => props.lines);
25
+ </script>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <div :class="classes">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue';
9
+ import { cn } from '../../utils/cn';
10
+
11
+ const props = withDefaults(
12
+ defineProps<{
13
+ gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
14
+ align?: 'stretch' | 'start' | 'center' | 'end';
15
+ class?: string;
16
+ }>(),
17
+ {
18
+ gap: 'md',
19
+ align: 'stretch',
20
+ },
21
+ );
22
+
23
+ const gapClasses = {
24
+ none: 'gap-0',
25
+ xs: 'gap-1',
26
+ sm: 'gap-2',
27
+ md: 'gap-4',
28
+ lg: 'gap-6',
29
+ xl: 'gap-8',
30
+ };
31
+
32
+ const alignClasses = {
33
+ stretch: 'items-stretch',
34
+ start: 'items-start',
35
+ center: 'items-center',
36
+ end: 'items-end',
37
+ };
38
+
39
+ const classes = computed(() =>
40
+ cn('flex flex-col', gapClasses[props.gap], alignClasses[props.align], props.class),
41
+ );
42
+ </script>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <div :class="classes">
3
+ <Icon v-if="icon" :name="icon" size="xl" class="mx-auto text-subtle-fg" />
4
+ <h3 v-if="title" class="text-base font-semibold text-foreground">
5
+ {{ title }}
6
+ </h3>
7
+ <p v-if="description" class="text-sm text-muted-foreground">
8
+ {{ description }}
9
+ </p>
10
+ <div v-if="$slots.actions" class="mt-2 flex justify-center">
11
+ <slot name="actions" />
12
+ </div>
13
+ <slot />
14
+ </div>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import { computed } from 'vue';
19
+ import { Icon } from '../base';
20
+ import { cn } from '../../utils/cn';
21
+
22
+ const props = withDefaults(
23
+ defineProps<{
24
+ icon?: string;
25
+ title?: string;
26
+ description?: string;
27
+ tone?: 'default' | 'error' | 'warning';
28
+ class?: string;
29
+ }>(),
30
+ {
31
+ tone: 'default',
32
+ },
33
+ );
34
+
35
+ const toneClasses = {
36
+ default: 'text-muted-foreground',
37
+ error: 'text-red-400',
38
+ warning: 'text-yellow-400',
39
+ };
40
+
41
+ const classes = computed(() =>
42
+ cn('py-8 text-center space-y-2', toneClasses[props.tone], props.class),
43
+ );
44
+ </script>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <div :class="classes">
3
+ <aside :class="leftClasses">
4
+ <slot name="left" />
5
+ </aside>
6
+ <main class="min-w-0 flex-1">
7
+ <slot />
8
+ </main>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { computed } from 'vue';
14
+ import { cn } from '../../utils/cn';
15
+
16
+ const props = withDefaults(
17
+ defineProps<{
18
+ leftWidth?: 'sm' | 'md' | 'lg';
19
+ class?: string;
20
+ leftClass?: string;
21
+ }>(),
22
+ {
23
+ leftWidth: 'md',
24
+ },
25
+ );
26
+
27
+ const widthClasses = {
28
+ sm: 'md:w-56',
29
+ md: 'md:w-72',
30
+ lg: 'md:w-96',
31
+ };
32
+
33
+ const classes = computed(() => cn('grid gap-4 md:flex', props.class));
34
+ const leftClasses = computed(() => cn('min-w-0 shrink-0', widthClasses[props.leftWidth], props.leftClass));
35
+ </script>
@@ -0,0 +1,160 @@
1
+ <template>
2
+ <div
3
+ ref="rootRef"
4
+ class="min-h-0 w-full overflow-y-auto overscroll-y-contain"
5
+ :class="containerClass"
6
+ @scroll.passive="onScroll"
7
+ >
8
+ <div
9
+ class="relative w-full"
10
+ :style="{ height: `${totalHeight}px` }"
11
+ >
12
+ <div
13
+ class="absolute left-0 right-0 top-0 will-change-transform"
14
+ :style="{ transform: `translate3d(0, ${offsetY}px, 0)` }"
15
+ >
16
+ <div
17
+ v-for="(item, i) in visibleSlice"
18
+ :key="itemKey(item, startIndex + i)"
19
+ :style="rowStyle(startIndex + i)"
20
+ >
21
+ <slot
22
+ name="default"
23
+ :item="item"
24
+ :index="startIndex + i"
25
+ />
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <div
30
+ v-if="hasAfterSlot"
31
+ ref="afterRef"
32
+ class="w-full shrink-0"
33
+ >
34
+ <slot name="after" />
35
+ </div>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup lang="ts">
40
+ import { computed, ref, useSlots, watch } from 'vue';
41
+ import { useResizeObserver } from '@vueuse/core';
42
+
43
+ const props = withDefaults(
44
+ defineProps<{
45
+ items: readonly unknown[];
46
+ /** Высота строки контента (px), без межстрочного зазора */
47
+ itemHeight?: number;
48
+ /** Зазор снизу у строки (кроме последней) */
49
+ itemGap?: number;
50
+ /** Дополнительные строки сверху/снизу вне вьюпорта */
51
+ overscan?: number;
52
+ itemKey: (item: unknown, index: number) => string | number | symbol;
53
+ containerClass?: string;
54
+ }>(),
55
+ {
56
+ itemHeight: 64,
57
+ itemGap: 4,
58
+ overscan: 8,
59
+ },
60
+ );
61
+
62
+ defineSlots<{
63
+ default(props: { item: unknown; index: number }): unknown;
64
+ after(): unknown;
65
+ }>();
66
+
67
+ const slots = useSlots();
68
+ const hasAfterSlot = computed(() => !!slots.after);
69
+
70
+ const rootRef = ref<HTMLElement | null>(null);
71
+ const afterRef = ref<HTMLElement | null>(null);
72
+ const scrollTop = ref(0);
73
+ const viewportHeight = ref(0);
74
+ const afterHeight = ref(0);
75
+
76
+ const stride = computed(
77
+ () => props.itemHeight + props.itemGap,
78
+ );
79
+
80
+ const totalHeight = computed(() => {
81
+ const n = props.items.length;
82
+ if (n === 0) return 0;
83
+ return (n - 1) * stride.value + props.itemHeight;
84
+ });
85
+
86
+ const scrollContentHeight = computed(
87
+ () => totalHeight.value + afterHeight.value,
88
+ );
89
+
90
+ const startIndex = computed(() => {
91
+ if (props.items.length === 0) return 0;
92
+ const raw = Math.floor(scrollTop.value / stride.value) - props.overscan;
93
+ return Math.max(0, raw);
94
+ });
95
+
96
+ const endIndex = computed(() => {
97
+ const n = props.items.length;
98
+ if (n === 0) return -1;
99
+ const first = Math.floor(scrollTop.value / stride.value);
100
+ const visibleCount = Math.ceil(viewportHeight.value / stride.value) + 2;
101
+ const raw = first + visibleCount + props.overscan;
102
+ return Math.min(n - 1, raw);
103
+ });
104
+
105
+ const visibleSlice = computed(() => {
106
+ const n = props.items.length;
107
+ if (n === 0 || startIndex.value > endIndex.value) return [];
108
+ if (scrollTop.value >= totalHeight.value) return [];
109
+ return props.items.slice(startIndex.value, endIndex.value + 1);
110
+ });
111
+
112
+ const offsetY = computed(() => startIndex.value * stride.value);
113
+
114
+ function rowStyle(index: number) {
115
+ const isLast = index === props.items.length - 1;
116
+ return {
117
+ height: `${props.itemHeight}px`,
118
+ marginBottom: isLast ? '0' : `${props.itemGap}px`,
119
+ };
120
+ }
121
+
122
+ function onScroll(e: Event) {
123
+ const el = e.target as HTMLElement;
124
+ scrollTop.value = el.scrollTop;
125
+ viewportHeight.value = el.clientHeight;
126
+ }
127
+
128
+ function measureViewport() {
129
+ const el = rootRef.value;
130
+ if (!el) return;
131
+ viewportHeight.value = el.clientHeight;
132
+ }
133
+
134
+ function clampScroll() {
135
+ const el = rootRef.value;
136
+ if (!el) return;
137
+ const max = Math.max(0, scrollContentHeight.value - el.clientHeight);
138
+ if (el.scrollTop > max) el.scrollTop = max;
139
+ }
140
+
141
+ useResizeObserver(rootRef, () => measureViewport());
142
+
143
+ useResizeObserver(afterRef, (entries) => {
144
+ const h = entries[0]?.contentRect.height ?? 0;
145
+ afterHeight.value = h;
146
+ });
147
+
148
+ watch(
149
+ [() => props.items.length, totalHeight, afterHeight],
150
+ () => clampScroll(),
151
+ );
152
+
153
+ watch(rootRef, (el) => {
154
+ if (el) measureViewport();
155
+ });
156
+
157
+ watch(hasAfterSlot, (on) => {
158
+ if (!on) afterHeight.value = 0;
159
+ });
160
+ </script>
@@ -0,0 +1,35 @@
1
+ export { default as Container } from './Container.vue';
2
+ export { default as Section } from './Section.vue';
3
+ export { default as Panel } from './Panel.vue';
4
+ export { default as Card } from './Card.vue';
5
+ export { default as Stack } from './Stack.vue';
6
+ export { default as Inline } from './Inline.vue';
7
+ export { default as Grid } from './Grid.vue';
8
+ export { default as PageSection } from './PageSection.vue';
9
+ export { default as StateBlock } from './StateBlock.vue';
10
+ export { default as Callout } from './Callout.vue';
11
+ export { default as BusyOverlay } from './BusyOverlay.vue';
12
+ export { default as EmptyState } from './EmptyState.vue';
13
+ export { default as FullscreenDimmer } from './FullscreenDimmer.vue';
14
+ export { default as LoadingState } from './LoadingState.vue';
15
+ export { default as OverlayWaitPanel } from './OverlayWaitPanel.vue';
16
+ export { default as PageToolbar } from './PageToolbar.vue';
17
+ export { default as ProgressBar } from './ProgressBar.vue';
18
+ export { default as SegmentedControl } from './SegmentedControl.vue';
19
+ export { default as SelectableCard } from './SelectableCard.vue';
20
+ export { default as SelectableRow } from './SelectableRow.vue';
21
+ export { default as MediaBox } from './MediaBox.vue';
22
+ export { default as EntityMediaRow } from './EntityMediaRow.vue';
23
+ export { default as TwoPaneLayout } from './TwoPaneLayout.vue';
24
+ export { default as FilterResultsLayout } from './FilterResultsLayout.vue';
25
+ export { default as FloatingPanel } from './FloatingPanel.vue';
26
+ export { default as OverlayPanel } from './OverlayPanel.vue';
27
+ export { default as Skeleton } from './Skeleton.vue';
28
+ export { default as SkeletonText } from './SkeletonText.vue';
29
+ export { default as SkeletonAvatar } from './SkeletonAvatar.vue';
30
+
31
+ export { default as SkeletonEntityCard } from './SkeletonEntityCard.vue';
32
+ export { default as SkeletonGrid } from './SkeletonGrid.vue';
33
+ export { default as SkeletonListRow } from './SkeletonListRow.vue';
34
+ export { default as SkeletonFeedPost } from './SkeletonFeedPost.vue';
35
+ export { default as VirtualList } from './VirtualList.vue';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Обводки/заливки скелетонов через CSS Vars: классы Tailwind из SFC `@rynt/sdk`
3
+ * могут не попадать в бандл; тогда у `border` остаётся ширина без цвета → solid currentColor (белый текст на dark).
4
+ */
5
+
6
+ export function skeletonBarSurfaceStyle(): Record<string, string> {
7
+ return {
8
+ boxSizing: 'border-box',
9
+ backgroundColor: 'color-mix(in srgb, var(--muted) 55%, transparent)',
10
+ boxShadow:
11
+ 'inset 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent)',
12
+ };
13
+ }
14
+
15
+ export function skeletonPanelShellStyle(
16
+ mutedOpacity: string,
17
+ borderPrimaryOpacity: string,
18
+ ): Record<string, string> {
19
+ return {
20
+ boxSizing: 'border-box',
21
+ border: `1px solid color-mix(in srgb, var(--primary) ${borderPrimaryOpacity}, transparent)`,
22
+ backgroundColor: `color-mix(in srgb, var(--muted) ${mutedOpacity}, transparent)`,
23
+ };
24
+ }
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <!-- Корневой размер задаём style — spacing из SDK-SFC может не попасть в Tailwind CSS; при только absolute-детях высота без явного height схлопывается в 0. -->
3
+ <div :style="navItemBoxStyle">
4
+ <button
5
+ type="button"
6
+ class="absolute inset-0 flex cursor-pointer items-center justify-center overflow-hidden border-0 bg-transparent p-0"
7
+ :style="{ borderRadius: 'var(--radius-ui-md)' }"
8
+ :title="title"
9
+ @click="$emit('click')"
10
+ >
11
+ <div class="absolute inset-0 group flex items-center justify-center">
12
+ <!-- Внешний border с градиентом -->
13
+ <div
14
+ :class="[
15
+ 'pointer-events-none absolute inset-0',
16
+ active
17
+ ? activeGradient
18
+ : 'bg-transparent group-hover:bg-gradient-to-br group-hover:from-primary group-hover:via-accent-secondary group-hover:to-primary-hover',
19
+ ]"
20
+ :style="{ borderRadius: 'var(--radius-ui-md)' }"
21
+ />
22
+
23
+ <!-- Внутренний фон (без transition на фоне — иначе при hover градиент просвечивает между кадрами) -->
24
+ <div
25
+ :class="[
26
+ 'pointer-events-none absolute inset-[2px]',
27
+ active
28
+ ? 'bg-background'
29
+ : 'bg-transparent group-hover:bg-background',
30
+ ]"
31
+ :style="innerFaceStyle"
32
+ />
33
+
34
+ <!-- Иконка -->
35
+ <div
36
+ v-if="!props.image"
37
+ :class="[
38
+ 'relative z-10 flex shrink-0 items-center justify-center transition-colors',
39
+ active
40
+ ? activeColor
41
+ : 'text-muted-foreground group-hover:text-accent-secondary',
42
+ ]"
43
+ >
44
+ <slot />
45
+ </div>
46
+ </div>
47
+
48
+ <!-- Статус индикатор (опционально) -->
49
+ <div v-if="status" class="absolute -top-0.5 -right-0.5 z-20">
50
+ <StatusIndicator :status="status" size="sm" />
51
+ </div>
52
+
53
+ <!-- Индикатор непрочитанных (опционально) -->
54
+ <div
55
+ v-if="badgeCount !== undefined && badgeCount > 0"
56
+ class="absolute -top-0.5 -right-0.5 z-20"
57
+ >
58
+ <div
59
+ class="h-2 w-2 shrink-0 bg-destructive shadow-[0_0_4px_color-mix(in_srgb,var(--destructive)_55%,transparent)]"
60
+ />
61
+ </div>
62
+ </button>
63
+
64
+ <!-- Индикатор активного пункта -->
65
+ <div
66
+ v-if="active && showIndicator"
67
+ class="absolute left-0 top-1/2 -translate-y-1/2 w-[3px] h-6 bg-accent-secondary -ml-1 shadow-[0_0_8px_color-mix(in_srgb,var(--primary)_55%,transparent)]"
68
+ style="clip-path: polygon(0 0, 100% 10%, 100% 90%, 0 100%)"
69
+ />
70
+ </div>
71
+ </template>
72
+
73
+ <script setup lang="ts">
74
+ import { computed } from 'vue';
75
+ import { StatusIndicator } from '../base';
76
+
77
+ /** 44×44 без Tailwind spacing: `h-11`/`w-11` из SDK-SFC часто не попадают в билд; без явной высоты и с absolute-детьми бокс даёт 44×0 в DevTools. */
78
+ const navItemBoxStyle = {
79
+ position: 'relative' as const,
80
+ width: '2.75rem',
81
+ height: '2.75rem',
82
+ minWidth: '2.75rem',
83
+ minHeight: '2.75rem',
84
+ flexShrink: 0,
85
+ };
86
+
87
+ interface Props {
88
+ active?: boolean;
89
+ title?: string;
90
+ variant?: 'default' | 'success';
91
+ status?: 'online' | 'offline';
92
+ image?: string;
93
+ showIndicator?: boolean;
94
+ badgeCount?: number;
95
+ }
96
+
97
+ const props = withDefaults(defineProps<Props>(), {
98
+ active: false,
99
+ variant: 'default',
100
+ showIndicator: true,
101
+ badgeCount: undefined,
102
+ });
103
+
104
+ /** Рамка 1 px через CSS: утилиты `border-*` из SDK могут не попасть в Tailwind-бандл. Неактивный — как раньше (primary ~16%); активный — прозрачная граница без скачка вёрстки. */
105
+ const innerFaceStyle = computed(() => {
106
+ const styles: Record<string, string> = {
107
+ boxSizing: 'border-box',
108
+ borderRadius: 'var(--radius-ui-sm)',
109
+ };
110
+ if (props.image) {
111
+ styles.backgroundImage = `url(${props.image})`;
112
+ styles.backgroundSize = 'cover';
113
+ styles.backgroundPosition = 'center';
114
+ }
115
+ if (!props.active) {
116
+ styles.border =
117
+ '1px solid color-mix(in srgb, var(--primary) 16%, transparent)';
118
+ } else {
119
+ styles.border = '1px solid transparent';
120
+ }
121
+ return styles;
122
+ });
123
+
124
+ const emit = defineEmits<{
125
+ click: [];
126
+ }>();
127
+
128
+ const activeGradient = computed(() => {
129
+ return props.variant === 'success'
130
+ ? 'bg-gradient-to-br from-success via-success/85 to-success/70'
131
+ : 'bg-gradient-to-br from-primary via-accent-secondary to-primary-hover';
132
+ });
133
+
134
+ const activeColor = computed(() => {
135
+ return props.variant === 'success'
136
+ ? 'text-success'
137
+ : 'text-accent-secondary';
138
+ });
139
+ </script>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <button :class="tabClasses" :disabled="disabled" @click="$emit('click')">
3
+ <slot />
4
+ </button>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue';
9
+ import { cn } from '../../utils/cn';
10
+
11
+ interface Props {
12
+ active?: boolean;
13
+ disabled?: boolean;
14
+ variant?: 'default' | 'pills' | 'rail';
15
+ }
16
+
17
+ const props = withDefaults(defineProps<Props>(), {
18
+ active: false,
19
+ disabled: false,
20
+ variant: 'default',
21
+ });
22
+
23
+ const emit = defineEmits<{
24
+ click: [];
25
+ }>();
26
+
27
+ const tabClasses = computed(() => {
28
+ if (props.variant === 'rail') {
29
+ const baseRail =
30
+ 'shrink-0 whitespace-nowrap rounded px-3 py-2.5 text-sm font-medium transition-colors flex items-center gap-2 cursor-pointer border-l-2 [&_svg]:opacity-80';
31
+ return cn(
32
+ baseRail,
33
+ props.active
34
+ ? 'border-primary bg-primary/10 text-foreground'
35
+ : 'border-transparent text-muted-foreground hover:bg-card hover:text-foreground',
36
+ props.disabled && 'opacity-50 cursor-not-allowed',
37
+ );
38
+ }
39
+
40
+ const baseClasses =
41
+ 'px-3 py-2 transition-colors flex items-center gap-1 cursor-pointer';
42
+
43
+ if (props.variant === 'pills') {
44
+ return cn(
45
+ baseClasses,
46
+ props.active
47
+ ? 'bg-primary text-primary-foreground'
48
+ : 'bg-surface-overlay text-muted-foreground hover:bg-secondary hover:text-foreground',
49
+ props.disabled && 'opacity-50 cursor-not-allowed',
50
+ );
51
+ }
52
+
53
+ return cn(
54
+ baseClasses,
55
+ props.active
56
+ ? 'bg-surface-raised text-foreground'
57
+ : 'text-muted-foreground hover:text-foreground hover:bg-secondary',
58
+ props.disabled && 'opacity-50 cursor-not-allowed',
59
+ );
60
+ });
61
+ </script>