Copy disabled (too large)
Download .txt
Showing preview only (27,323K chars total). Download the full file to get everything.
Repository: GoogleForCreators/web-stories-wp
Branch: main
Commit: 65b196460fbf
Files: 4493
Total size: 25.1 MB
Directory structure:
gitextract_qcnlwv5k/
├── .allstar/
│ └── branch_protection.yaml
├── .browserslistrc
├── .distignore
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ ├── enhancement.md
│ │ ├── epic.md
│ │ └── task.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── SUPPORT.md
│ ├── dependabot.yml
│ ├── release.yml
│ └── workflows/
│ ├── build-and-deploy.yml
│ ├── codeql-analysis.yml
│ ├── deploy-storybook.yml
│ ├── lint-css-js-md.yml
│ ├── lint-i18n.yml
│ ├── lint-php.yml
│ ├── lint-plugin-check.yml
│ ├── npm-release.yml
│ ├── plugin-release.yml
│ ├── scorecards.yml
│ ├── tests-e2e.yml
│ ├── tests-karma-dashboard.yml
│ ├── tests-karma-editor.yml
│ ├── tests-unit-js.yml
│ ├── tests-unit-php.yml
│ ├── update-browserslist.yml
│ ├── update-google-fonts.yml
│ ├── update-product-schema.yml
│ └── update-templates.yml
├── .gitignore
├── .husky/
│ └── pre-commit
├── .markdownlint.json
├── .markdownlintignore
├── .npmpackagejsonlintrc.json
├── .npmrc
├── .nvmrc
├── .oxlintrc.json
├── .phpstorm.config.js
├── .phpstorm.meta.php
├── .prettierignore
├── .prettierrc
├── .storybook/
│ ├── main.cjs
│ ├── manager-head.html
│ ├── preview-head.html
│ ├── preview.js
│ └── stories/
│ └── playground/
│ ├── dashboard/
│ │ ├── index.js
│ │ └── theme.js
│ └── story-editor/
│ ├── api/
│ │ ├── fonts.js
│ │ ├── index.js
│ │ ├── media.js
│ │ └── story.js
│ ├── constants.js
│ ├── getDummyMedia.js
│ ├── header/
│ │ ├── buttons/
│ │ │ ├── index.js
│ │ │ ├── preview.js
│ │ │ └── saveButton.js
│ │ └── index.js
│ ├── index.js
│ └── preview.js
├── .stylelintignore
├── .stylelintrc
├── .wordpress-org/
│ ├── README.md
│ └── blueprints/
│ └── blueprint.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── __mocks__/
│ ├── colorthief.js
│ ├── node:fs.js
│ └── react-moveable.js
├── __static__/
│ ├── README.md
│ ├── asteroid.ogg
│ ├── beach.webm
│ └── ranger9.ogg
├── babel.config.cjs
├── bin/
│ ├── deploy-to-test-environment.sh
│ ├── install-wp-tests.sh
│ ├── local-env/
│ │ ├── docker-compose.yml
│ │ ├── includes.sh
│ │ ├── install-wordpress.sh
│ │ ├── launch-containers.sh
│ │ ├── start.sh
│ │ ├── stop.sh
│ │ └── uploads.ini
│ ├── schemas/
│ │ └── story.json
│ ├── setup-local-npm-registry.sh
│ ├── stop-local-npm-registry.sh
│ └── verdaccio-config.yml
├── blocks/
│ └── embed/
│ └── block.json
├── codecov.yml
├── composer.json
├── docs/
│ ├── README.md
│ ├── accessibility-guidelines.md
│ ├── accessibility-testing.md
│ ├── animations.md
│ ├── architecture.md
│ ├── browser-support.md
│ ├── canvas.md
│ ├── cdn.md
│ ├── checklist.md
│ ├── code-style.md
│ ├── design-docs.md
│ ├── design-panel-push-update-flow.md
│ ├── design-system.md
│ ├── devtools.md
│ ├── e2e-tests.md
│ ├── environment-variables.md
│ ├── external-template-creation.md
│ ├── feature-flags.md
│ ├── getting-started.md
│ ├── glossary.md
│ ├── integration-tests.md
│ ├── local-environment.md
│ ├── migrations.md
│ ├── onboarding.md
│ ├── page-templates.md
│ ├── performance.md
│ ├── quick-actions.md
│ ├── right-click-menu.md
│ ├── storybook.md
│ ├── svgs.md
│ ├── testing-environments.md
│ ├── testing-qa.md
│ ├── third-party-integration/
│ │ ├── dashboard/
│ │ │ ├── README.md
│ │ │ ├── api-callbacks.md
│ │ │ ├── getting-started.md
│ │ │ ├── integration-layer.md
│ │ │ └── tutorial.md
│ │ └── story-editor/
│ │ ├── README.md
│ │ ├── api-callbacks.md
│ │ ├── getting-started.md
│ │ ├── integration-layer.md
│ │ └── tutorial.md
│ ├── unit-tests.md
│ ├── web-stories-embeds.md
│ └── workflows.md
├── includes/
│ ├── AMP/
│ │ ├── Canonical_Sanitizer.php
│ │ ├── Integration/
│ │ │ └── AMP_Story_Sanitizer.php
│ │ ├── Meta_Sanitizer.php
│ │ ├── Optimization.php
│ │ ├── Output_Buffer.php
│ │ ├── Sanitization.php
│ │ ├── Story_Sanitizer.php
│ │ ├── Tag_And_Attribute_Sanitizer.php
│ │ └── Traits/
│ │ └── Sanitization_Utils.php
│ ├── AMP_Story_Player_Assets.php
│ ├── AdSense.php
│ ├── Ad_Manager.php
│ ├── Admin/
│ │ ├── Activation_Notice.php
│ │ ├── Admin.php
│ │ ├── Cross_Origin_Isolation.php
│ │ ├── Customizer.php
│ │ ├── Dashboard.php
│ │ ├── Editor.php
│ │ ├── Google_Fonts.php
│ │ ├── Meta_Boxes.php
│ │ ├── PluginActionLinks.php
│ │ ├── PluginRowMeta.php
│ │ ├── Site_Health.php
│ │ └── TinyMCE.php
│ ├── Analytics.php
│ ├── Assets.php
│ ├── Block/
│ │ └── Web_Stories_Block.php
│ ├── Context.php
│ ├── Database_Upgrader.php
│ ├── Decoder.php
│ ├── Demo_Content.php
│ ├── Discovery.php
│ ├── Embed_Base.php
│ ├── Exception/
│ │ ├── FailedToMakeInstance.php
│ │ ├── InvalidEventProperties.php
│ │ ├── InvalidService.php
│ │ ├── SanitizationException.php
│ │ └── WebStoriesException.php
│ ├── Experiments.php
│ ├── Font_Post_Type.php
│ ├── Infrastructure/
│ │ ├── Conditional.php
│ │ ├── Delayed.php
│ │ ├── HasMeta.php
│ │ ├── HasRequirements.php
│ │ ├── Injector/
│ │ │ ├── FallbackInstantiator.php
│ │ │ ├── InjectionChain.php
│ │ │ └── SimpleInjector.php
│ │ ├── Injector.php
│ │ ├── Instantiator.php
│ │ ├── Plugin.php
│ │ ├── PluginActivationAware.php
│ │ ├── PluginDeactivationAware.php
│ │ ├── PluginUninstallAware.php
│ │ ├── Registerable.php
│ │ ├── Service.php
│ │ ├── ServiceBasedPlugin.php
│ │ ├── ServiceContainer/
│ │ │ ├── LazilyInstantiatedService.php
│ │ │ └── SimpleServiceContainer.php
│ │ ├── ServiceContainer.php
│ │ ├── SiteInitializationAware.php
│ │ └── SiteRemovalAware.php
│ ├── Integrations/
│ │ ├── AMP.php
│ │ ├── Conditional_Featured_Image.php
│ │ ├── Core_Themes_Support.php
│ │ ├── Ezoic.php
│ │ ├── Jetpack.php
│ │ ├── New_Relic.php
│ │ ├── NextGen_Gallery.php
│ │ ├── Plugin_Status.php
│ │ ├── ShortPixel.php
│ │ ├── Site_Kit.php
│ │ └── WooCommerce.php
│ ├── Interfaces/
│ │ ├── Field.php
│ │ ├── FieldState.php
│ │ ├── FieldStateFactory.php
│ │ ├── Migration.php
│ │ ├── Product_Query.php
│ │ └── Renderer.php
│ ├── KSES.php
│ ├── Locale.php
│ ├── Media/
│ │ ├── Base_Color.php
│ │ ├── Blurhash.php
│ │ ├── Cropping.php
│ │ ├── Image_Sizes.php
│ │ ├── Media_Source_Taxonomy.php
│ │ ├── SVG.php
│ │ ├── Types.php
│ │ └── Video/
│ │ ├── Captions.php
│ │ ├── Is_Gif.php
│ │ ├── Muting.php
│ │ ├── Optimization.php
│ │ ├── Poster.php
│ │ └── Trimming.php
│ ├── Mgid.php
│ ├── Migrations/
│ │ ├── Add_Media_Source.php
│ │ ├── Add_Media_Source_Editor.php
│ │ ├── Add_Media_Source_Gif_Conversion.php
│ │ ├── Add_Media_Source_Page_Template.php
│ │ ├── Add_Media_Source_Recording.php
│ │ ├── Add_Media_Source_Source_Image.php
│ │ ├── Add_Media_Source_Source_Video.php
│ │ ├── Add_Media_Source_Video_Optimization.php
│ │ ├── Add_Poster_Generation_Media_Source.php
│ │ ├── Add_Stories_Caps.php
│ │ ├── Add_VideoPress_Poster_Generation_Media_Source.php
│ │ ├── Migrate_Base.php
│ │ ├── Migration_Meta_To_Term.php
│ │ ├── Remove_Broken_Text_Styles.php
│ │ ├── Remove_Incorrect_Tracking_Id.php
│ │ ├── Remove_Unneeded_Attachment_Meta.php
│ │ ├── Replace_Conic_Style_Presets.php
│ │ ├── Rewrite_Flush.php
│ │ ├── Set_Legacy_Analytics_Usage_Flag.php
│ │ ├── Unify_Color_Presets.php
│ │ ├── Update_1.php
│ │ └── Update_Publisher_Logos.php
│ ├── Model/
│ │ └── Story.php
│ ├── Page_Template_Post_Type.php
│ ├── Plugin.php
│ ├── PluginFactory.php
│ ├── Post_Type_Base.php
│ ├── REST_API/
│ │ ├── Embed_Controller.php
│ │ ├── Font_Controller.php
│ │ ├── Hotlinking_Controller.php
│ │ ├── Link_Controller.php
│ │ ├── Page_Template_Controller.php
│ │ ├── Products_Controller.php
│ │ ├── Publisher_Logos_Controller.php
│ │ ├── REST_Controller.php
│ │ ├── Status_Check_Controller.php
│ │ ├── Stories_Autosaves_Controller.php
│ │ ├── Stories_Base_Controller.php
│ │ ├── Stories_Controller.php
│ │ ├── Stories_Lock_Controller.php
│ │ ├── Stories_Media_Controller.php
│ │ ├── Stories_Settings_Controller.php
│ │ ├── Stories_Taxonomies_Controller.php
│ │ ├── Stories_Terms_Controller.php
│ │ └── Stories_Users_Controller.php
│ ├── Register_Widget.php
│ ├── Remove_Transients.php
│ ├── Renderer/
│ │ ├── Archives.php
│ │ ├── Feed.php
│ │ ├── Oembed.php
│ │ ├── Single.php
│ │ ├── Stories/
│ │ │ ├── Carousel_Renderer.php
│ │ │ ├── FieldState/
│ │ │ │ ├── BaseFieldState.php
│ │ │ │ ├── CarouselView.php
│ │ │ │ ├── CircleView.php
│ │ │ │ ├── GridView.php
│ │ │ │ └── ListView.php
│ │ │ ├── FieldStateFactory/
│ │ │ │ └── Factory.php
│ │ │ ├── Fields/
│ │ │ │ └── BaseField.php
│ │ │ ├── Generic_Renderer.php
│ │ │ └── Renderer.php
│ │ └── Story/
│ │ ├── Embed.php
│ │ ├── HTML.php
│ │ ├── Image.php
│ │ └── Singleton.php
│ ├── Service_Base.php
│ ├── Services.php
│ ├── Settings.php
│ ├── Shopping/
│ │ ├── Product.php
│ │ ├── Product_Meta.php
│ │ ├── Shopify_Query.php
│ │ ├── Shopping_Vendors.php
│ │ └── WooCommerce_Query.php
│ ├── Shortcode/
│ │ ├── Embed_Shortcode.php
│ │ └── Stories_Shortcode.php
│ ├── Stories_Script_Data.php
│ ├── Story_Archive.php
│ ├── Story_Post_Type.php
│ ├── Story_Query.php
│ ├── Story_Revisions.php
│ ├── Taxonomy/
│ │ ├── Category_Taxonomy.php
│ │ ├── Tag_Taxonomy.php
│ │ └── Taxonomy_Base.php
│ ├── Tracking.php
│ ├── User/
│ │ ├── Capabilities.php
│ │ └── Preferences.php
│ ├── Widgets/
│ │ └── Stories.php
│ ├── compat/
│ │ ├── Web_Stories_Compatibility.php
│ │ └── amp.php
│ ├── data/
│ │ ├── fonts/
│ │ │ └── fonts.json
│ │ └── stories/
│ │ └── demo.json
│ ├── functions.php
│ ├── namespace.php
│ ├── polyfills/
│ │ └── mbstring.php
│ └── templates/
│ ├── admin/
│ │ ├── activation-notice.php
│ │ ├── dashboard.php
│ │ ├── edit-story.php
│ │ └── experiments.php
│ └── frontend/
│ ├── embed-web-story.php
│ └── single-web-story.php
├── jest-puppeteer.config.cjs
├── jsconfig.json
├── karma-dashboard.config.cjs
├── karma-story-editor.config.cjs
├── package.json
├── packages/
│ ├── activation-notice/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── components/
│ │ │ │ │ ├── dismiss.tsx
│ │ │ │ │ ├── image.tsx
│ │ │ │ │ ├── link.tsx
│ │ │ │ │ ├── messageContent.tsx
│ │ │ │ │ ├── number.tsx
│ │ │ │ │ ├── paragraph.tsx
│ │ │ │ │ ├── step1.tsx
│ │ │ │ │ ├── step2.tsx
│ │ │ │ │ ├── step3.tsx
│ │ │ │ │ ├── successMessage.tsx
│ │ │ │ │ └── test/
│ │ │ │ │ ├── dismiss.js
│ │ │ │ │ ├── step1.js
│ │ │ │ │ ├── step2.js
│ │ │ │ │ ├── step3.js
│ │ │ │ │ └── successMessage.js
│ │ │ │ ├── config/
│ │ │ │ │ ├── configProvider.tsx
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useConfig.ts
│ │ │ │ └── index.tsx
│ │ │ ├── index.tsx
│ │ │ ├── stories/
│ │ │ │ └── index.js
│ │ │ ├── testUtils/
│ │ │ │ ├── index.js
│ │ │ │ └── renderWithTheme.js
│ │ │ ├── theme.ts
│ │ │ └── typings/
│ │ │ └── styled-components.d.ts
│ │ └── tsconfig.json
│ ├── animation/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── components/
│ │ │ │ ├── AMPAnimations.tsx
│ │ │ │ ├── AMPKeyframes.tsx
│ │ │ │ ├── AMPWrapper.tsx
│ │ │ │ ├── WAAPIWrapper.tsx
│ │ │ │ ├── animationMachine.ts
│ │ │ │ ├── context.ts
│ │ │ │ ├── fullSizeAbsolute.ts
│ │ │ │ ├── generateKeyframesMap.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── provider.tsx
│ │ │ │ ├── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── test/
│ │ │ │ │ ├── WAAPIWrapper.tsx
│ │ │ │ │ ├── animationProvider.tsx
│ │ │ │ │ └── generateKeyframesMap.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── useStoryAnimationContext.ts
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── outputs/
│ │ │ │ ├── animationOutput.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── keyframesOutput.tsx
│ │ │ │ ├── output.tsx
│ │ │ │ └── types.ts
│ │ │ ├── parts/
│ │ │ │ ├── createAnimation.tsx
│ │ │ │ ├── createAnimationPart.ts
│ │ │ │ ├── defaultFields.ts
│ │ │ │ ├── effects/
│ │ │ │ │ ├── backgroundPan.ts
│ │ │ │ │ ├── backgroundPanAndZoom.ts
│ │ │ │ │ ├── backgroundZoom.ts
│ │ │ │ │ ├── drop.ts
│ │ │ │ │ ├── fadeIn.ts
│ │ │ │ │ ├── flyIn.tsx
│ │ │ │ │ ├── pan.ts
│ │ │ │ │ ├── pulse.ts
│ │ │ │ │ ├── rotateIn.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── drop.js
│ │ │ │ │ │ ├── fadeIn.js
│ │ │ │ │ │ ├── flyIn.js
│ │ │ │ │ │ ├── pan.js
│ │ │ │ │ │ ├── pulse.js
│ │ │ │ │ │ ├── rotateIn.js
│ │ │ │ │ │ ├── twirlIn.js
│ │ │ │ │ │ ├── whooshIn.js
│ │ │ │ │ │ └── zoom.js
│ │ │ │ │ ├── twirlIn.tsx
│ │ │ │ │ ├── whooshIn.tsx
│ │ │ │ │ └── zoom.tsx
│ │ │ │ ├── emptyAnimationPart.tsx
│ │ │ │ ├── getAnimationEffectFields.ts
│ │ │ │ ├── index.tsx
│ │ │ │ ├── simple/
│ │ │ │ │ ├── blinkOn.ts
│ │ │ │ │ ├── bounce.ts
│ │ │ │ │ ├── fade.ts
│ │ │ │ │ ├── flip.ts
│ │ │ │ │ ├── floatOn.ts
│ │ │ │ │ ├── move.ts
│ │ │ │ │ ├── pulse.ts
│ │ │ │ │ ├── spin.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── blinkOn.js
│ │ │ │ │ │ ├── bounce.js
│ │ │ │ │ │ ├── fade.js
│ │ │ │ │ │ ├── flip.js
│ │ │ │ │ │ ├── floatOn.js
│ │ │ │ │ │ ├── move.js
│ │ │ │ │ │ ├── pulse.js
│ │ │ │ │ │ ├── spin.js
│ │ │ │ │ │ └── zoom.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── pulse.ts
│ │ │ │ │ └── zoom.ts
│ │ │ │ └── types.ts
│ │ │ ├── storybookUtils/
│ │ │ │ ├── index.js
│ │ │ │ └── utils/
│ │ │ │ └── ampBoilerplate.js
│ │ │ ├── types/
│ │ │ │ ├── animation.ts
│ │ │ │ ├── effects.ts
│ │ │ │ ├── element.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── keyframes.ts
│ │ │ │ ├── propTypes.ts
│ │ │ │ └── storyAnimationState.ts
│ │ │ ├── typings/
│ │ │ │ └── global.d.ts
│ │ │ └── utils/
│ │ │ ├── createKeyframeEffect.ts
│ │ │ ├── defaultUnit.ts
│ │ │ ├── generateLookupMap.ts
│ │ │ ├── getDefaultFieldValue.ts
│ │ │ ├── getElementOffsets.ts
│ │ │ ├── getGlobalSpace.ts
│ │ │ ├── getInitialStyleFromKeyframes.ts
│ │ │ ├── getOffPageOffset.ts
│ │ │ ├── getTotalDuration.ts
│ │ │ ├── index.ts
│ │ │ ├── orderByKeys.ts
│ │ │ ├── padArray.ts
│ │ │ ├── sanitizeTimings.ts
│ │ │ └── test/
│ │ │ ├── createKeyframeEffect.ts
│ │ │ ├── defaultUnit.ts
│ │ │ ├── generateLookupMap.ts
│ │ │ ├── getElementOffsets.ts
│ │ │ ├── getGlobalSpace.ts
│ │ │ ├── getInitialStyleFromKeyframes.ts
│ │ │ ├── getOffPageOffset.ts
│ │ │ ├── getTotalDuration.ts
│ │ │ ├── orderByKeys.ts
│ │ │ ├── padArray.ts
│ │ │ └── sanitizeTimings.ts
│ │ └── tsconfig.json
│ ├── commander/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── utils/
│ │ │ ├── appendRevisionToVersion.ts
│ │ │ ├── bundlePlugin.ts
│ │ │ ├── copyFiles.ts
│ │ │ ├── createBuild.ts
│ │ │ ├── deleteExistingZipFiles.ts
│ │ │ ├── generateZipFile.ts
│ │ │ ├── getCurrentVersionNumber.ts
│ │ │ ├── getIgnoredFiles.ts
│ │ │ ├── index.ts
│ │ │ ├── resizeSvgPath.ts
│ │ │ ├── test/
│ │ │ │ ├── appendRevisionToVersion.js
│ │ │ │ ├── bundlePlugin.js
│ │ │ │ ├── copyFiles.js
│ │ │ │ ├── createBuild.js
│ │ │ │ ├── deleteExistingZipFiles.js
│ │ │ │ ├── generateZipFile.js
│ │ │ │ ├── getCurrentVersionNumber.js
│ │ │ │ ├── getIgnoredFiles.js
│ │ │ │ ├── resizeSvgPaths.js
│ │ │ │ ├── updateCdnUrl.js
│ │ │ │ └── updateVersionNumbers.js
│ │ │ ├── updateCdnUrl.ts
│ │ │ └── updateVersionNumbers.ts
│ │ └── tsconfig.json
│ ├── dashboard/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── api/
│ │ │ │ │ ├── apiProvider.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── apiProvider.js
│ │ │ │ │ ├── useApi.js
│ │ │ │ │ ├── useApiAlerts.js
│ │ │ │ │ ├── useStoryApi.js
│ │ │ │ │ ├── useTaxonomyApi.js
│ │ │ │ │ ├── useTemplateApi.js
│ │ │ │ │ └── useUsersApi.js
│ │ │ │ ├── config/
│ │ │ │ │ ├── configProvider.tsx
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useConfig.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── reducer/
│ │ │ │ │ ├── story/
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── storyReducer.js
│ │ │ │ │ ├── templates/
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── templateReducer.js
│ │ │ │ │ └── test/
│ │ │ │ │ ├── story.js
│ │ │ │ │ └── templates.js
│ │ │ │ ├── router/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── route.ts
│ │ │ │ │ ├── routerProvider.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── route.js
│ │ │ │ │ │ ├── router.js
│ │ │ │ │ │ └── routerProvider.js
│ │ │ │ │ └── useRouteHistory.ts
│ │ │ │ ├── serializers/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── templates.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── templates.js
│ │ │ │ ├── textContent/
│ │ │ │ │ └── index.js
│ │ │ │ └── views/
│ │ │ │ ├── apiAlerts/
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── constants.js
│ │ │ │ ├── exploreTemplates/
│ │ │ │ │ ├── content/
│ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── templateGridItem.js
│ │ │ │ │ │ ├── templateGridView.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── content.js
│ │ │ │ │ ├── filters/
│ │ │ │ │ │ ├── TemplateFiltersProvider/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── templateFiltersProvider.js
│ │ │ │ │ │ └── useTemplateFilters.js
│ │ │ │ │ ├── header/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── header.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── exploreTemplates.karma.js
│ │ │ │ │ ├── modal/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── templateDetails/
│ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ ├── content/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── header/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── header.js
│ │ │ │ │ │ └── karma/
│ │ │ │ │ │ └── templateDetails.karma.js
│ │ │ │ │ ├── templateFilters.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── templateFilters.js
│ │ │ │ ├── filters/
│ │ │ │ │ ├── reducer.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── reducer.js
│ │ │ │ │ └── types.js
│ │ │ │ ├── index.js
│ │ │ │ ├── myStories/
│ │ │ │ │ ├── content/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── listView/
│ │ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── storiesView/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── storyGridItem/
│ │ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── storyDisplayContent.js
│ │ │ │ │ │ ├── storyGridView/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── storyListItem/
│ │ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ ├── content.js
│ │ │ │ │ │ └── storiesView.js
│ │ │ │ │ ├── filters/
│ │ │ │ │ │ ├── StoryFiltersProvider/
│ │ │ │ │ │ │ ├── author/
│ │ │ │ │ │ │ │ └── useAuthorFilter.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── taxonomy/
│ │ │ │ │ │ │ └── useTaxonomyFilters.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── storyFiltersProvider.js
│ │ │ │ │ │ │ ├── useAuthorFilter.js
│ │ │ │ │ │ │ └── useTaxonomyFilter.js
│ │ │ │ │ │ └── useStoryFilters.js
│ │ │ │ │ ├── header/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── storyStatusToggle.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── header.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── karma/
│ │ │ │ │ ├── myStories.karma.js
│ │ │ │ │ └── myStoriesList.karma.js
│ │ │ │ ├── shared/
│ │ │ │ │ ├── bodyViewOptions.js
│ │ │ │ │ ├── emptyContentMessage.js
│ │ │ │ │ ├── grid/
│ │ │ │ │ │ └── components.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── pageHeading.js
│ │ │ │ │ ├── sortDropDown.js
│ │ │ │ │ └── stories/
│ │ │ │ │ ├── emptyContentMessage.js
│ │ │ │ │ └── pageHeading.js
│ │ │ │ └── utils/
│ │ │ │ ├── composeTemplateFilter.js
│ │ │ │ ├── getSearchOptions.js
│ │ │ │ ├── getTemplateFilters.js
│ │ │ │ ├── index.js
│ │ │ │ └── test/
│ │ │ │ ├── composeTemplateFilter.js
│ │ │ │ ├── getSearchOptions.js
│ │ │ │ └── getTemplateFilters.js
│ │ │ ├── components/
│ │ │ │ ├── cardGallery/
│ │ │ │ │ ├── components.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── cardGrid/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── card-grid.js
│ │ │ │ ├── cardGridItem/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── cardGridItem.js
│ │ │ │ ├── colorList/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── contentGutter/
│ │ │ │ │ └── index.js
│ │ │ │ ├── dialog/
│ │ │ │ │ ├── dialog.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── fileUpload/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── fileUpload.js
│ │ │ │ ├── index.js
│ │ │ │ ├── inlineInputForm/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── inlineInputForm.js
│ │ │ │ ├── interfaceSkeleton/
│ │ │ │ │ └── index.js
│ │ │ │ ├── layout/
│ │ │ │ │ ├── fixed.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── provider.js
│ │ │ │ │ ├── scrollable.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── useLayoutContext.js
│ │ │ │ │ └── useLayoutContext.js
│ │ │ │ ├── navProvider.js
│ │ │ │ ├── pageStructure/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── leftRail.js
│ │ │ │ │ ├── menuButton.js
│ │ │ │ │ ├── navigationComponents.js
│ │ │ │ │ ├── pageStructureComponents.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── menuButton.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── pageStructure.js
│ │ │ │ ├── popoverMenu/
│ │ │ │ │ ├── story-menu-generator.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── story-menu-generator.js
│ │ │ │ ├── scrollToTop/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── scrollToTop.js
│ │ │ │ ├── storyMenu/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── storyMenu.js
│ │ │ │ ├── table/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── table.js
│ │ │ │ ├── tooltip/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── tooltip.js
│ │ │ │ ├── types.js
│ │ │ │ └── viewStyleBar/
│ │ │ │ ├── index.js
│ │ │ │ ├── stories/
│ │ │ │ │ └── index.js
│ │ │ │ └── test/
│ │ │ │ └── viewStyleBar.js
│ │ │ ├── constants/
│ │ │ │ ├── components.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── pageStructure.ts
│ │ │ │ ├── stories.ts
│ │ │ │ └── templates.ts
│ │ │ ├── dashboard.js
│ │ │ ├── dataUtils/
│ │ │ │ ├── formattedStoriesArray.js
│ │ │ │ ├── formattedTaxonomiesArray.js
│ │ │ │ ├── formattedTaxonomyTermsObject.js
│ │ │ │ ├── formattedTemplatesArray.js
│ │ │ │ └── formattedUsersObject.js
│ │ │ ├── getDefaultConfig.js
│ │ │ ├── icons/
│ │ │ │ ├── index.ts
│ │ │ │ └── stories/
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ ├── karma/
│ │ │ │ ├── apiProviderFixture.js
│ │ │ │ ├── fixture.js
│ │ │ │ └── integrationLayerTesting/
│ │ │ │ └── config.karma.js
│ │ │ ├── propTypes.js
│ │ │ ├── storybookUtils/
│ │ │ │ └── index.js
│ │ │ ├── testUtils/
│ │ │ │ ├── groupTemplatesByTag.js
│ │ │ │ ├── index.js
│ │ │ │ ├── mockApiProvider.js
│ │ │ │ └── renderWithProviders.js
│ │ │ ├── theme.js
│ │ │ ├── types/
│ │ │ │ ├── configProvider.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── routerProvider.ts
│ │ │ ├── typings/
│ │ │ │ └── svg.d.ts
│ │ │ └── utils/
│ │ │ ├── groupBy.js
│ │ │ ├── index.js
│ │ │ ├── keyboardOnlyOutline.js
│ │ │ ├── noop.js
│ │ │ ├── test/
│ │ │ │ ├── groupBy.js
│ │ │ │ ├── useDashboardResultsLabel.js
│ │ │ │ ├── usePagePreviewSize.js
│ │ │ │ ├── useStoryView.js
│ │ │ │ └── useTemplateView.js
│ │ │ ├── titleFormatted.js
│ │ │ ├── useDashboardResultsLabel.js
│ │ │ ├── usePagePreviewSize.js
│ │ │ ├── useStoryView.js
│ │ │ └── useTemplateView.js
│ │ └── tsconfig.json
│ ├── date/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── convertFormatString.ts
│ │ │ ├── format.ts
│ │ │ ├── formatDate.ts
│ │ │ ├── formatDistance.ts
│ │ │ ├── formatTime.ts
│ │ │ ├── getOptions.ts
│ │ │ ├── getRelativeDisplayDate.ts
│ │ │ ├── getTimeZoneString.ts
│ │ │ ├── hasLeadingZeros.ts
│ │ │ ├── index.ts
│ │ │ ├── is12Hour.ts
│ │ │ ├── settings.ts
│ │ │ ├── test/
│ │ │ │ ├── convertFormatString.ts
│ │ │ │ ├── format.ts
│ │ │ │ ├── formatDate.ts
│ │ │ │ ├── formatTime.ts
│ │ │ │ ├── getRelativeDisplayDate.ts
│ │ │ │ ├── getTimeZoneString.ts
│ │ │ │ ├── hasLeadingZeros.ts
│ │ │ │ ├── is12Hour.ts
│ │ │ │ └── toUTCDate.ts
│ │ │ ├── third_party/
│ │ │ │ └── buildLocalizeFn.ts
│ │ │ └── toUTCDate.ts
│ │ └── tsconfig.json
│ ├── design-system/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── components/
│ │ │ │ ├── banner/
│ │ │ │ │ ├── banner.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── button/
│ │ │ │ │ ├── button.tsx
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── button.js
│ │ │ │ │ └── toggleButton.tsx
│ │ │ │ ├── checkbox/
│ │ │ │ │ ├── checkbox.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── checkbox.js
│ │ │ │ ├── chip/
│ │ │ │ │ ├── chip.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── index.js
│ │ │ │ ├── circularProgress/
│ │ │ │ │ ├── circular.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── contextMenu/
│ │ │ │ │ ├── animationContainer.tsx
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── button.tsx
│ │ │ │ │ │ ├── group.tsx
│ │ │ │ │ │ ├── icon.tsx
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── item.tsx
│ │ │ │ │ │ ├── label.ts
│ │ │ │ │ │ ├── link.tsx
│ │ │ │ │ │ ├── separator.tsx
│ │ │ │ │ │ ├── shortcut.ts
│ │ │ │ │ │ ├── styles.ts
│ │ │ │ │ │ ├── subMenuTrigger.tsx
│ │ │ │ │ │ └── suffix.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── contextMenu.tsx
│ │ │ │ │ ├── contextMenuProvider/
│ │ │ │ │ │ ├── context.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── provider.tsx
│ │ │ │ │ │ └── useContextMenu.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── menu.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styled.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── contextMenu.js
│ │ │ │ │ └── types.ts
│ │ │ │ ├── datalist/
│ │ │ │ │ ├── container.tsx
│ │ │ │ │ ├── datalist.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── list/
│ │ │ │ │ │ ├── defaultRenderer.tsx
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── list.tsx
│ │ │ │ │ │ └── styled.ts
│ │ │ │ │ ├── searchInput.tsx
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── dialog/
│ │ │ │ │ ├── dialog.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── dialog.js
│ │ │ │ ├── disclosure/
│ │ │ │ │ ├── disclosure.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dropDown/
│ │ │ │ │ ├── components.ts
│ │ │ │ │ ├── dropdown.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── select/
│ │ │ │ │ │ ├── components.ts
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ └── select.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── dropDown.js
│ │ │ │ │ │ ├── select.js
│ │ │ │ │ │ └── useDropDown.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── useDropDown.ts
│ │ │ │ ├── hex/
│ │ │ │ │ ├── hex.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.ts
│ │ │ │ ├── infiniteScroller/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── infiniteScroller.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── infiniteScroller.js
│ │ │ │ ├── input/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── input.tsx
│ │ │ │ │ ├── numericInput.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styled.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── input.js
│ │ │ │ │ │ ├── useNumericInput.js
│ │ │ │ │ │ └── validation.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── useNumericInput.tsx
│ │ │ │ │ └── validation.ts
│ │ │ │ ├── keyboard/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── gridview/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── getArrowDir.js
│ │ │ │ │ │ │ ├── getColumn.js
│ │ │ │ │ │ │ ├── getIndex.js
│ │ │ │ │ │ │ └── getRow.js
│ │ │ │ │ │ ├── useGridViewKeys.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── keyboard.tsx
│ │ │ │ │ ├── keys.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── createShortcutAriaLabel.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── prettifyShortcut.js
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── loadingBar/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── loadingBar.tsx
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── loadingSpinner/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── loadingSpinner.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── loadingSpinner.js
│ │ │ │ ├── mediaInput/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── mediaInput.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── mediaInput.js
│ │ │ │ │ └── types.ts
│ │ │ │ ├── menu/
│ │ │ │ │ ├── components.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── list/
│ │ │ │ │ │ ├── components.ts
│ │ │ │ │ │ ├── defaultListItem.tsx
│ │ │ │ │ │ ├── emptyList.tsx
│ │ │ │ │ │ ├── groupLabel.tsx
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── list.tsx
│ │ │ │ │ │ └── listGroup.tsx
│ │ │ │ │ ├── menu.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── menu.js
│ │ │ │ │ │ ├── useDropDownMenu.js
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── useDropDownMenu.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── modal/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── modal.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styles.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── modal.js
│ │ │ │ ├── notificationBubble/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── notificationBubble.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── types.ts
│ │ │ │ ├── pill/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── pill.tsx
│ │ │ │ │ ├── pillGroup.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── pill.js
│ │ │ │ ├── popup/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── popup.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── popup.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── getOffset.ts
│ │ │ │ │ ├── getTransforms.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── radio/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── radio.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── radio.js
│ │ │ │ ├── search/
│ │ │ │ │ ├── components.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── input/
│ │ │ │ │ │ ├── components.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── input.tsx
│ │ │ │ │ ├── search.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── input.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── input.js
│ │ │ │ │ │ ├── search.js
│ │ │ │ │ │ └── useSearch.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── useSearch.ts
│ │ │ │ ├── slider/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── slider.tsx
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── snackbar/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── snackbarContainer.tsx
│ │ │ │ │ ├── snackbarMessage.tsx
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── snackbarContainer.js
│ │ │ │ │ │ └── snackbarMessage.js
│ │ │ │ │ └── types.ts
│ │ │ │ ├── swatch/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── swatch.tsx
│ │ │ │ ├── switch/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── switch.tsx
│ │ │ │ │ └── test/
│ │ │ │ │ └── switch.js
│ │ │ │ ├── textArea/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── textArea.js
│ │ │ │ │ └── textArea.tsx
│ │ │ │ ├── toggle/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── toggle.js
│ │ │ │ │ └── toggle.tsx
│ │ │ │ ├── tooltip/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── tail.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── tooltip.js
│ │ │ │ │ └── tooltip.tsx
│ │ │ │ ├── typography/
│ │ │ │ │ ├── display/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── headline/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── link/
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ └── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── list/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styles.ts
│ │ │ │ │ └── text/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ └── visuallyHidden.ts
│ │ │ ├── contexts/
│ │ │ │ ├── index.ts
│ │ │ │ ├── popup/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── popupProvider.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── usePopup.ts
│ │ │ │ └── snackbar/
│ │ │ │ ├── context.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── snackbarProvider.tsx
│ │ │ │ └── useSnackbar.ts
│ │ │ ├── icons/
│ │ │ │ ├── index.ts
│ │ │ │ └── stories/
│ │ │ │ └── index.js
│ │ │ ├── images/
│ │ │ │ ├── index.ts
│ │ │ │ └── stories/
│ │ │ │ └── index.js
│ │ │ ├── index.ts
│ │ │ ├── stories/
│ │ │ │ └── index.js
│ │ │ ├── storybookUtils/
│ │ │ │ ├── darkThemeProvider.js
│ │ │ │ ├── index.js
│ │ │ │ └── sampleData.js
│ │ │ ├── testUtils/
│ │ │ │ ├── index.js
│ │ │ │ ├── queryById.js
│ │ │ │ ├── renderWithProviders.js
│ │ │ │ └── sampleData.js
│ │ │ ├── theme/
│ │ │ │ ├── borders.ts
│ │ │ │ ├── breakpoint.ts
│ │ │ │ ├── colors.ts
│ │ │ │ ├── constants/
│ │ │ │ │ ├── breakpoints.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── global/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── styles.ts
│ │ │ │ ├── helpers/
│ │ │ │ │ ├── centerContent.ts
│ │ │ │ │ ├── expandPresetStyles.ts
│ │ │ │ │ ├── fullSize.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── outline.ts
│ │ │ │ │ ├── scrollbar.ts
│ │ │ │ │ ├── transparentBg.ts
│ │ │ │ │ └── visuallyHidden.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── stories/
│ │ │ │ │ ├── colors.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── theme.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── typography.ts
│ │ │ ├── types/
│ │ │ │ ├── keyboard.ts
│ │ │ │ ├── snackbar.ts
│ │ │ │ ├── theme.ts
│ │ │ │ └── typography.ts
│ │ │ ├── typings/
│ │ │ │ ├── styled.d.ts
│ │ │ │ └── svg.d.ts
│ │ │ └── utils/
│ │ │ ├── constants.ts
│ │ │ ├── deepMerge.ts
│ │ │ ├── directions.ts
│ │ │ ├── getKeyboardMovement.ts
│ │ │ ├── index.ts
│ │ │ ├── isNullOrUndefinedOrEmptyString.ts
│ │ │ ├── labelAccessibilityValidator.ts
│ │ │ ├── localStore.ts
│ │ │ ├── noop.ts
│ │ │ ├── panelSections.ts
│ │ │ ├── panelTypes.ts
│ │ │ ├── sessionStore.ts
│ │ │ ├── test/
│ │ │ │ ├── deepMerge.js
│ │ │ │ ├── labelAccessibilityValidator.js
│ │ │ │ ├── uniqueEntriesByKey.js
│ │ │ │ ├── useLiveRegion.js
│ │ │ │ └── useMouseDownOutside.js
│ │ │ ├── uniqueEntriesByKey.ts
│ │ │ ├── useForwardedRef.ts
│ │ │ ├── useLiveRegion.ts
│ │ │ └── useMouseDownOutsideRef.ts
│ │ └── tsconfig.json
│ ├── dom/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── ensureFontLoaded.ts
│ │ │ ├── escapeHTML.ts
│ │ │ ├── index.ts
│ │ │ ├── loadStylesheet.ts
│ │ │ ├── stripHTML.ts
│ │ │ └── test/
│ │ │ └── escapeHTML.ts
│ │ └── tsconfig.json
│ ├── e2e-test-utils/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── activatePlugin.js
│ │ ├── activateRTL.js
│ │ ├── addRequestInterception.js
│ │ ├── addTextElement.js
│ │ ├── checkVersion.js
│ │ ├── config.js
│ │ ├── createNewPost.js
│ │ ├── createNewStory.js
│ │ ├── createNewTerm.js
│ │ ├── createURL.js
│ │ ├── customFonts.js
│ │ ├── deactivatePlugin.js
│ │ ├── deactivateRTL.js
│ │ ├── deleteAllMedia.js
│ │ ├── deleteMedia.js
│ │ ├── deleteWidgets.js
│ │ ├── disableCheckbox.js
│ │ ├── editStoryWithTitle.js
│ │ ├── enableCheckbox.js
│ │ ├── experimentalFeatures.js
│ │ ├── getFileName.js
│ │ ├── index.js
│ │ ├── insertStoryTitle.js
│ │ ├── insertWidget.js
│ │ ├── isCurrentURL.js
│ │ ├── loadPostEditor.js
│ │ ├── loginUser.js
│ │ ├── logoutUser.js
│ │ ├── minWPVersionRequired.js
│ │ ├── previewStory.js
│ │ ├── publishPost.js
│ │ ├── publishStory.js
│ │ ├── setAnalyticsCode.js
│ │ ├── shopping.js
│ │ ├── takeSnapshot.js
│ │ ├── toggleVideoOptimization.js
│ │ ├── toolbarProfileOption.js
│ │ ├── trashAllPosts.js
│ │ ├── trashAllTerms.js
│ │ ├── triggerHighPriorityChecklistSection.js
│ │ ├── uploadFile.js
│ │ ├── uploadMedia.js
│ │ ├── uploadPublisherLogo.js
│ │ ├── user.js
│ │ ├── visitAdminPage.js
│ │ ├── visitBlockWidgetScreen.js
│ │ ├── visitDashboard.js
│ │ ├── visitSettings.js
│ │ ├── withPlugin.js
│ │ ├── withRTL.js
│ │ └── withUser.js
│ ├── e2e-tests/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── assets/
│ │ │ ├── README.md
│ │ │ ├── small-video.webm
│ │ │ └── test.vtt
│ │ ├── config/
│ │ │ └── bootstrap.js
│ │ ├── jest.config.js
│ │ ├── plugins/
│ │ │ ├── disable-block-directory.php
│ │ │ ├── disable-gravatar.php
│ │ │ ├── locked-post-mock.php
│ │ │ ├── site-kit-adsense.php
│ │ │ ├── site-kit-analytics.php
│ │ │ ├── status-check-200-invalid.php
│ │ │ ├── status-check-403.php
│ │ │ ├── status-check-500.php
│ │ │ ├── web-stories-cors-error.php
│ │ │ ├── web-stories-disable-default-templates.php
│ │ │ ├── web-stories-disable-media3p.php
│ │ │ ├── web-stories-embed.php
│ │ │ ├── web-stories-hotlink.php
│ │ │ ├── web-stories-meta-box.php
│ │ │ └── web-stories-taxonomies.php
│ │ ├── puppeteerEnvironment.js
│ │ ├── specs/
│ │ │ ├── dashboard/
│ │ │ │ ├── adminMenu.js
│ │ │ │ ├── dashboard.js
│ │ │ │ ├── documentTitle.js
│ │ │ │ ├── myStories.js
│ │ │ │ ├── noJS.js
│ │ │ │ ├── settings/
│ │ │ │ │ ├── adminUser/
│ │ │ │ │ │ ├── analytics.js
│ │ │ │ │ │ ├── customFonts.js
│ │ │ │ │ │ ├── dataRemovalSettings.js
│ │ │ │ │ │ ├── monetization.js
│ │ │ │ │ │ ├── publisherLogo.js
│ │ │ │ │ │ ├── shoppingProvider.js
│ │ │ │ │ │ ├── telemetryBanner.js
│ │ │ │ │ │ └── videoSettings.js
│ │ │ │ │ ├── authorUser.js
│ │ │ │ │ ├── contributorUser.js
│ │ │ │ │ └── editorUser.js
│ │ │ │ ├── telemetryBanner.js
│ │ │ │ └── templates/
│ │ │ │ └── useTemplate.js
│ │ │ ├── editor/
│ │ │ │ ├── authorUser.js
│ │ │ │ ├── backgroundAudio.js
│ │ │ │ ├── contributorUser.js
│ │ │ │ ├── editor.js
│ │ │ │ ├── floatingMenu.js
│ │ │ │ ├── fontCheck.js
│ │ │ │ ├── media/
│ │ │ │ │ ├── hotlinking.js
│ │ │ │ │ ├── insert3PMedia.js
│ │ │ │ │ ├── insertMediaFromDialog.js
│ │ │ │ │ ├── insertMediaFromLibrary.js
│ │ │ │ │ ├── insertMovVideo.js
│ │ │ │ │ ├── insertWebMVideo.js
│ │ │ │ │ └── svg.js
│ │ │ │ ├── metaBoxes.js
│ │ │ │ ├── noJS.js
│ │ │ │ ├── pageTemplates.js
│ │ │ │ ├── passwordProtected.js
│ │ │ │ ├── pendingStories.js
│ │ │ │ ├── prePublishChecklist/
│ │ │ │ │ ├── adminUser.js
│ │ │ │ │ └── contributorUser.js
│ │ │ │ ├── publishPanel/
│ │ │ │ │ └── adminUser.js
│ │ │ │ ├── publishingFlow.js
│ │ │ │ ├── saveStory.js
│ │ │ │ ├── shopping/
│ │ │ │ │ ├── productMenu.js
│ │ │ │ │ ├── schema.json
│ │ │ │ │ └── woocommerce.js
│ │ │ │ ├── sidebar.js
│ │ │ │ ├── statusCheck.js
│ │ │ │ ├── storyDetailsModal/
│ │ │ │ │ ├── adminUser.js
│ │ │ │ │ └── contributorUser.js
│ │ │ │ ├── taxonomy.js
│ │ │ │ └── templates.js
│ │ │ ├── integrations/
│ │ │ │ ├── amp.js
│ │ │ │ └── sitekit.js
│ │ │ └── wordpress/
│ │ │ ├── adminMenu.js
│ │ │ ├── archive.js
│ │ │ ├── blockWidget.js
│ │ │ ├── corsCheck.js
│ │ │ ├── getStartedStory.js
│ │ │ ├── pluginActivation.js
│ │ │ ├── postLocking.js
│ │ │ ├── quickEdit.js
│ │ │ ├── tinymce.js
│ │ │ ├── webStoriesBlock.js
│ │ │ └── widget.js
│ │ └── utils/
│ │ ├── constants.js
│ │ └── index.js
│ ├── element-library/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── audioSticker/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.tsx
│ │ │ │ ├── output.tsx
│ │ │ │ └── test/
│ │ │ │ └── output.js
│ │ │ ├── constants.ts
│ │ │ ├── elementTypes.ts
│ │ │ ├── gif/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── edit.tsx
│ │ │ │ ├── frame.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.ts
│ │ │ │ ├── output.tsx
│ │ │ │ └── test/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ └── output.js.snap
│ │ │ │ └── output.js
│ │ │ ├── image/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── edit.tsx
│ │ │ │ ├── frame.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.ts
│ │ │ │ ├── output.tsx
│ │ │ │ └── test/
│ │ │ │ └── output.js
│ │ │ ├── index.ts
│ │ │ ├── media/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── edit.tsx
│ │ │ │ ├── editCropMoveable.tsx
│ │ │ │ ├── editPanMoveable.tsx
│ │ │ │ ├── frame.tsx
│ │ │ │ ├── imageDisplay.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── output.tsx
│ │ │ │ ├── scalePanel.tsx
│ │ │ │ ├── textContent.ts
│ │ │ │ ├── util.ts
│ │ │ │ └── videoImage.tsx
│ │ │ ├── product/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.tsx
│ │ │ │ └── output.tsx
│ │ │ ├── shape/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.ts
│ │ │ │ ├── output.tsx
│ │ │ │ └── test/
│ │ │ │ └── output.js
│ │ │ ├── shared/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── shared.ts
│ │ │ │ ├── useCSSVarColorTransformHandler.ts
│ │ │ │ ├── useColorTransformHandler.ts
│ │ │ │ └── visibleImage.tsx
│ │ │ ├── sticker/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.ts
│ │ │ │ └── output.tsx
│ │ │ ├── test/
│ │ │ │ └── index.js
│ │ │ ├── text/
│ │ │ │ ├── constants.ts
│ │ │ │ ├── display.tsx
│ │ │ │ ├── edit.tsx
│ │ │ │ ├── frame.tsx
│ │ │ │ ├── icon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── layer.ts
│ │ │ │ ├── output.tsx
│ │ │ │ ├── outputWithUnits.tsx
│ │ │ │ ├── test/
│ │ │ │ │ ├── output.js
│ │ │ │ │ └── util.js
│ │ │ │ ├── textContent.ts
│ │ │ │ ├── updateForResizeEvent.ts
│ │ │ │ └── util.ts
│ │ │ ├── typings/
│ │ │ │ ├── global.d.ts
│ │ │ │ ├── images.d.ts
│ │ │ │ ├── styled.d.ts
│ │ │ │ └── svg.d.ts
│ │ │ ├── utils/
│ │ │ │ ├── noop.ts
│ │ │ │ └── textMeasurements.tsx
│ │ │ └── video/
│ │ │ ├── captions.tsx
│ │ │ ├── constants.ts
│ │ │ ├── controls.tsx
│ │ │ ├── display.tsx
│ │ │ ├── edit.tsx
│ │ │ ├── frame.tsx
│ │ │ ├── icon.tsx
│ │ │ ├── index.ts
│ │ │ ├── layer.ts
│ │ │ ├── onDropHandler.ts
│ │ │ ├── output.tsx
│ │ │ ├── playPauseButton.tsx
│ │ │ ├── test/
│ │ │ │ └── output.js
│ │ │ └── trim.tsx
│ │ └── tsconfig.json
│ ├── elements/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── elementType.ts
│ │ │ ├── index.ts
│ │ │ ├── propTypes.ts
│ │ │ ├── types/
│ │ │ │ ├── data.ts
│ │ │ │ ├── element.ts
│ │ │ │ ├── elementDefinition.ts
│ │ │ │ ├── elementType.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── media.ts
│ │ │ │ ├── page.ts
│ │ │ │ ├── story.ts
│ │ │ │ └── taxonomies.ts
│ │ │ └── utils/
│ │ │ ├── createNewElement.ts
│ │ │ ├── createPage.ts
│ │ │ ├── duplicateElement.ts
│ │ │ ├── duplicatePage.ts
│ │ │ ├── elementIs.ts
│ │ │ ├── getDefinitionForType.ts
│ │ │ ├── getLayerName.ts
│ │ │ ├── getOffsetCoordinates.ts
│ │ │ ├── getTransformFlip.ts
│ │ │ ├── index.ts
│ │ │ └── isElementBelowLimit.ts
│ │ └── tsconfig.json
│ ├── eslint-import-resolver/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ └── index.cjs
│ ├── fonts/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ ├── cli.ts
│ │ │ └── utils/
│ │ │ ├── buildFonts.ts
│ │ │ ├── constants.ts
│ │ │ ├── getFontFallback.ts
│ │ │ ├── getFontMetrics.ts
│ │ │ ├── normalizeFont.ts
│ │ │ ├── test/
│ │ │ │ ├── buildFonts.js
│ │ │ │ ├── getFontFallback.js
│ │ │ │ ├── getFontMetrics.js
│ │ │ │ └── normalizeFont.js
│ │ │ └── types.ts
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── fonts.json
│ │ │ ├── index.ts
│ │ │ ├── test/
│ │ │ │ └── curatedFonts.ts
│ │ │ ├── types.ts
│ │ │ └── utils/
│ │ │ ├── getFontCSS.ts
│ │ │ ├── getGoogleFontURL.ts
│ │ │ ├── index.ts
│ │ │ └── test/
│ │ │ ├── getFontCSS.js
│ │ │ └── getGoogleFontURL.js
│ │ └── tsconfig.json
│ ├── glider/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── i18n/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── i18n.ts
│ │ │ ├── index.ts
│ │ │ ├── sprintf.ts
│ │ │ ├── test/
│ │ │ │ ├── transformNode.tsx
│ │ │ │ ├── translateToExclusiveList.ts
│ │ │ │ ├── translateToInclusiveList.ts
│ │ │ │ └── translateWithMarkup.tsx
│ │ │ ├── transformNode.ts
│ │ │ ├── translateToExclusiveList.ts
│ │ │ ├── translateToInclusiveList.ts
│ │ │ ├── translateWithMarkup.tsx
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── jest-amp/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── index.js
│ │ ├── toBeValidAMP.js
│ │ ├── toBeValidAMPStoryElement.js
│ │ ├── toBeValidAMPStoryPage.js
│ │ └── utils.js
│ ├── jest-puppeteer-amp/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── index.js
│ │ └── toBeValidAMP.js
│ ├── jest-resolver/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ └── index.cjs
│ ├── karma-failed-tests-reporter/
│ │ ├── .eslintrc
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ └── index.cjs
│ ├── karma-fixture/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── actPromise.js
│ │ ├── client_with_context.html
│ │ ├── componentStub.js
│ │ ├── events.js
│ │ ├── index.js
│ │ └── init.js
│ ├── karma-puppeteer-client/
│ │ ├── .eslintrc
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── client.js
│ │ └── index.cjs
│ ├── karma-puppeteer-launcher/
│ │ ├── .eslintrc
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── index.cjs
│ │ ├── mouseWithDnd.cjs
│ │ └── snapshot.cjs
│ ├── masks/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── borderedMaskedElement.tsx
│ │ │ ├── constants.ts
│ │ │ ├── display.tsx
│ │ │ ├── frame.tsx
│ │ │ ├── index.ts
│ │ │ ├── masks.ts
│ │ │ ├── output.tsx
│ │ │ ├── test/
│ │ │ │ ├── constants.js
│ │ │ │ └── output.js
│ │ │ ├── types.ts
│ │ │ ├── typings/
│ │ │ │ └── styled-components.d.ts
│ │ │ └── utils/
│ │ │ └── elementBorder.ts
│ │ └── tsconfig.json
│ ├── media/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── aspectRatiosApproximatelyMatch.ts
│ │ │ ├── blob.ts
│ │ │ ├── blobToFile.ts
│ │ │ ├── calculateSrcSet.ts
│ │ │ ├── createFileReader.ts
│ │ │ ├── createResource.ts
│ │ │ ├── fetchRemoteBlob.ts
│ │ │ ├── fetchRemoteFile.ts
│ │ │ ├── formatDuration.ts
│ │ │ ├── formatMsToHMS.ts
│ │ │ ├── getCanvasBlob.ts
│ │ │ ├── getFileBasename.ts
│ │ │ ├── getFileNameFromUrl.ts
│ │ │ ├── getFirstFrameOfVideo.ts
│ │ │ ├── getFocalFromOffset.ts
│ │ │ ├── getImageDimensions.ts
│ │ │ ├── getImageFromVideo.ts
│ │ │ ├── getMediaSizePositionProps.ts
│ │ │ ├── getMsFromHMS.ts
│ │ │ ├── getResourceSize.ts
│ │ │ ├── getSmallestUrlForWidth.ts
│ │ │ ├── getTypeFromMime.ts
│ │ │ ├── getVideoLength.ts
│ │ │ ├── getVideoLengthDisplay.ts
│ │ │ ├── hasVideoGotAudio.ts
│ │ │ ├── index.ts
│ │ │ ├── isAnimatedGif.ts
│ │ │ ├── mimeTypes.ts
│ │ │ ├── preloadImage.ts
│ │ │ ├── preloadVideo.ts
│ │ │ ├── preloadVideoMetadata.ts
│ │ │ ├── readFile.ts
│ │ │ ├── resourceIs.ts
│ │ │ ├── resourceList.ts
│ │ │ ├── seekVideo.ts
│ │ │ ├── test/
│ │ │ │ ├── calculateSrcSet.ts
│ │ │ │ ├── formatMsToHMS.ts
│ │ │ │ ├── getFileBasename.ts
│ │ │ │ ├── getMsFromHMS.ts
│ │ │ │ ├── getResourceSize.ts
│ │ │ │ ├── getSmallestUrlForWidth.ts
│ │ │ │ ├── getVideoLengthDisplay.ts
│ │ │ │ ├── isAnimatedGif.ts
│ │ │ │ ├── mimeTypes.ts
│ │ │ │ └── resourceList.ts
│ │ │ ├── types/
│ │ │ │ ├── audioResource.ts
│ │ │ │ ├── gifResource.ts
│ │ │ │ ├── imageResource.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── mediaElement.ts
│ │ │ │ ├── propTypes.ts
│ │ │ │ ├── resource.ts
│ │ │ │ ├── resourceCache.ts
│ │ │ │ ├── resourceInput.ts
│ │ │ │ ├── resourceType.ts
│ │ │ │ ├── sequenceResource.ts
│ │ │ │ └── videoResource.ts
│ │ │ └── typings/
│ │ │ └── dom.d.ts
│ │ └── tsconfig.json
│ ├── migration/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── scripts/
│ │ │ ├── cli.js
│ │ │ └── utils/
│ │ │ ├── test/
│ │ │ │ └── updateTemplates.js
│ │ │ └── updateTemplates.js
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ ├── migrate.ts
│ │ │ ├── migrations/
│ │ │ │ ├── test/
│ │ │ │ │ ├── v0001_storyDataArrayToObject.js
│ │ │ │ │ ├── v0002_dataPixelTo1080.js
│ │ │ │ │ ├── v0003_fullbleedToFill.js
│ │ │ │ │ ├── v0004_mediaElementToResource.js
│ │ │ │ │ ├── v0004_squareToShape.js
│ │ │ │ │ ├── v0005_setOpacity.js
│ │ │ │ │ ├── v0006_colorToPattern.js
│ │ │ │ │ ├── v0007_setFlip.js
│ │ │ │ │ ├── v0008_paddingToObject.js
│ │ │ │ │ ├── v0009_defaultBackground.js
│ │ │ │ │ ├── v0010_dataPixelTo440.js
│ │ │ │ │ ├── v0011_pageAdvancement.js
│ │ │ │ │ ├── v0012_setBackgroundTextMode.js
│ │ │ │ │ ├── v0013_videoIdToId.js
│ │ │ │ │ ├── v0014_oneTapLinkDeprecate.js
│ │ │ │ │ ├── v0015_fontObjects.js
│ │ │ │ │ ├── v0016_isFullbleedDeprecate.js
│ │ │ │ │ ├── v0017_inlineTextProperties.js
│ │ │ │ │ ├── v0018_defaultBackgroundElement.js
│ │ │ │ │ ├── v0019_conicToLinear.js
│ │ │ │ │ ├── v0020_isFillDeprecate.js
│ │ │ │ │ ├── v0021_backgroundColorToPage.js
│ │ │ │ │ ├── v0022_dataPixelTo412.js
│ │ │ │ │ ├── v0023_convertOverlayPattern.js
│ │ │ │ │ ├── v0024_blobsToSingleBlob.js
│ │ │ │ │ ├── v0025_singleAnimationTarget.js
│ │ │ │ │ ├── v0026_backgroundOverlayToOverlay.js
│ │ │ │ │ ├── v0027_videoDuration.js
│ │ │ │ │ ├── v0028_mark3pVideoAsOptimized.js
│ │ │ │ │ ├── v0029_unifyGifResources.js
│ │ │ │ │ ├── v0030_mark3pVideoAsMuted.js
│ │ │ │ │ ├── v0031_normalizeResourceSizes.js
│ │ │ │ │ ├── v0032_pageOutlinkTheme.js
│ │ │ │ │ ├── v0033_removeTitleFromResource.js
│ │ │ │ │ ├── v0034_removeUnusedBackgroundProps.js
│ │ │ │ │ ├── v0035_markVideoAsExternal.js
│ │ │ │ │ ├── v0036_changeBaseColorToHex.js
│ │ │ │ │ ├── v0038_camelCaseResourceSizes.js
│ │ │ │ │ ├── v0038_removeTransientMediaProperties.js
│ │ │ │ │ ├── v0039_backgroundAudioFormatting.js
│ │ │ │ │ ├── v0040_andadaFontToAndadaPro.js
│ │ │ │ │ ├── v0041_removeFontProperties.js
│ │ │ │ │ ├── v0042_removeTrackName.js
│ │ │ │ │ ├── v0043_removeTagNames.js
│ │ │ │ │ ├── v0044_unusedProperties.js
│ │ │ │ │ ├── v0045_globalPageAdvancement.js
│ │ │ │ │ ├── v0046_removeRedundantScalingProperties.js
│ │ │ │ │ ├── v0047_fixBrokenTemplates.js
│ │ │ │ │ └── v0048_removeBasedOnFromElements.js
│ │ │ │ ├── v0001_storyDataArrayToObject.ts
│ │ │ │ ├── v0002_dataPixelTo1080.ts
│ │ │ │ ├── v0003_fullbleedToFill.ts
│ │ │ │ ├── v0004_mediaElementToResource.ts
│ │ │ │ ├── v0004_squareToShape.ts
│ │ │ │ ├── v0005_setOpacity.ts
│ │ │ │ ├── v0006_colorToPattern.ts
│ │ │ │ ├── v0007_setFlip.ts
│ │ │ │ ├── v0008_paddingToObject.ts
│ │ │ │ ├── v0009_defaultBackground.ts
│ │ │ │ ├── v0010_dataPixelTo440.ts
│ │ │ │ ├── v0011_pageAdvancement.ts
│ │ │ │ ├── v0012_setBackgroundTextMode.ts
│ │ │ │ ├── v0013_videoIdToId.ts
│ │ │ │ ├── v0014_oneTapLinkDeprecate.ts
│ │ │ │ ├── v0015_fontObjects.ts
│ │ │ │ ├── v0016_isFullbleedDeprecate.ts
│ │ │ │ ├── v0017_inlineTextProperties.ts
│ │ │ │ ├── v0018_defaultBackgroundElement.ts
│ │ │ │ ├── v0019_conicToLinear.ts
│ │ │ │ ├── v0020_isFillDeprecate.ts
│ │ │ │ ├── v0021_backgroundColorToPage.ts
│ │ │ │ ├── v0022_dataPixelTo412.ts
│ │ │ │ ├── v0023_convertOverlayPattern.ts
│ │ │ │ ├── v0024_blobsToSingleBlob.ts
│ │ │ │ ├── v0025_singleAnimationTarget.ts
│ │ │ │ ├── v0026_backgroundOverlayToOverlay.ts
│ │ │ │ ├── v0027_videoDuration.ts
│ │ │ │ ├── v0028_mark3pVideoAsOptimized.ts
│ │ │ │ ├── v0029_unifyGifResources.ts
│ │ │ │ ├── v0030_mark3pVideoAsMuted.ts
│ │ │ │ ├── v0031_normalizeResourceSizes.ts
│ │ │ │ ├── v0032_pageOutlinkTheme.ts
│ │ │ │ ├── v0033_removeTitleFromResources.ts
│ │ │ │ ├── v0034_removeUnusedBackgroundProps.ts
│ │ │ │ ├── v0035_markVideoAsExternal.ts
│ │ │ │ ├── v0036_changeBaseColorToHex.ts
│ │ │ │ ├── v0037_removeTransientMediaProperties.ts
│ │ │ │ ├── v0038_camelCaseResourceSizes.ts
│ │ │ │ ├── v0039_backgroundAudioFormatting.ts
│ │ │ │ ├── v0040_andadaFontToAndadaPro.ts
│ │ │ │ ├── v0041_removeFontProperties.ts
│ │ │ │ ├── v0042_removeTrackName.ts
│ │ │ │ ├── v0043_removeTagNames.ts
│ │ │ │ ├── v0044_unusedProperties.ts
│ │ │ │ ├── v0045_globalPageAdvancement.ts
│ │ │ │ ├── v0046_removeRedundantScalingProperties.ts
│ │ │ │ ├── v0047_fixBrokenTemplates.ts
│ │ │ │ └── v0048_removeBasedOnFromElements.ts
│ │ │ └── types/
│ │ │ ├── element.ts
│ │ │ ├── index.ts
│ │ │ ├── pattern.ts
│ │ │ ├── resource.ts
│ │ │ └── story.ts
│ │ └── tsconfig.json
│ ├── moveable/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── areEventsDragging.ts
│ │ │ ├── cropStyle.ts
│ │ │ ├── index.ts
│ │ │ ├── moveStyle.ts
│ │ │ ├── moveable.tsx
│ │ │ ├── overlay/
│ │ │ │ ├── context.ts
│ │ │ │ ├── index.tsx
│ │ │ │ └── withOverlay.tsx
│ │ │ ├── test/
│ │ │ │ └── areEventsDragging.ts
│ │ │ └── typings/
│ │ │ ├── styled-components.d.ts
│ │ │ └── svg-imports.d.ts
│ │ └── tsconfig.json
│ ├── output/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── components/
│ │ │ │ └── withLink/
│ │ │ │ ├── index.tsx
│ │ │ │ └── test/
│ │ │ │ └── output.tsx
│ │ │ ├── constants.ts
│ │ │ ├── element.tsx
│ │ │ ├── index.ts
│ │ │ ├── page.tsx
│ │ │ ├── story.tsx
│ │ │ ├── test/
│ │ │ │ ├── __snapshots__/
│ │ │ │ │ ├── page.tsx.snap
│ │ │ │ │ └── textElement.tsx.snap
│ │ │ │ ├── _utils/
│ │ │ │ │ └── constants.ts
│ │ │ │ ├── page.tsx
│ │ │ │ ├── story.tsx
│ │ │ │ └── textElement.tsx
│ │ │ ├── types.ts
│ │ │ ├── typings/
│ │ │ │ ├── global.d.ts
│ │ │ │ ├── jest.d.ts
│ │ │ │ └── svg.d.ts
│ │ │ └── utils/
│ │ │ ├── ampBoilerplate.tsx
│ │ │ ├── backgroundAudio.tsx
│ │ │ ├── fontDeclarations.tsx
│ │ │ ├── getAutoAdvanceAfter.ts
│ │ │ ├── getLongestMediaElement.ts
│ │ │ ├── getPreloadResources.ts
│ │ │ ├── getStoryMarkup.tsx
│ │ │ ├── getTextElementTagNames.ts
│ │ │ ├── getUsedAmpExtensions.ts
│ │ │ ├── outlink.tsx
│ │ │ ├── populateElementFontData.ts
│ │ │ ├── shoppingAttachment.tsx
│ │ │ ├── styles.tsx
│ │ │ └── test/
│ │ │ ├── fontDeclarations.tsx
│ │ │ ├── getAutoAdvanceAfter.ts
│ │ │ ├── getLongestMediaElement.ts
│ │ │ ├── getPreloadResources.ts
│ │ │ ├── getStoryMarkup.ts
│ │ │ ├── getTextElementTagNames.ts
│ │ │ ├── getUsedAmpExtensions.ts
│ │ │ └── populateElementFontData.ts
│ │ └── tsconfig.json
│ ├── patterns/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── convertToCSS.ts
│ │ │ ├── createSolid.ts
│ │ │ ├── createSolidFromString.ts
│ │ │ ├── generatePatternStyles.ts
│ │ │ ├── getColorFromGradientStyle.ts
│ │ │ ├── getGradientStyleFromColor.ts
│ │ │ ├── getHexFromSolid.ts
│ │ │ ├── getHexFromSolidArray.ts
│ │ │ ├── getHexFromValue.ts
│ │ │ ├── getOpaquePattern.ts
│ │ │ ├── getPreviewText.ts
│ │ │ ├── getSolidFromHex.ts
│ │ │ ├── hasGradient.ts
│ │ │ ├── hasOpacity.ts
│ │ │ ├── index.ts
│ │ │ ├── isHexColorString.ts
│ │ │ ├── isPatternEqual.ts
│ │ │ ├── test/
│ │ │ │ ├── convertToCSS.ts
│ │ │ │ ├── createSolid.ts
│ │ │ │ ├── createSolidFromString.ts
│ │ │ │ ├── generatePatternStyles.ts
│ │ │ │ ├── getColorFromGradientStyle.ts
│ │ │ │ ├── getHexFromValue.ts
│ │ │ │ ├── getOpaquePattern.ts
│ │ │ │ ├── getPreviewText.ts
│ │ │ │ ├── getSolidFromHex.ts
│ │ │ │ └── hasOpacity.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── react/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── context.ts
│ │ │ ├── index.ts
│ │ │ ├── react-dom.ts
│ │ │ ├── react.ts
│ │ │ ├── renderToStaticMarkup.ts
│ │ │ ├── shallowEqual.ts
│ │ │ ├── test/
│ │ │ │ ├── context.js
│ │ │ │ └── useCombinedRefs.js
│ │ │ ├── typings/
│ │ │ │ └── global.d.ts
│ │ │ ├── useBatchingCallback.ts
│ │ │ ├── useCombinedRefs.ts
│ │ │ ├── useContextSelector.ts
│ │ │ ├── useFocusOut.ts
│ │ │ ├── useInitializedValue.ts
│ │ │ ├── usePrevious.ts
│ │ │ ├── useResizeEffect.ts
│ │ │ ├── useUnmount.ts
│ │ │ └── useWhyDidYouUpdate.ts
│ │ └── tsconfig.json
│ ├── rich-text/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── context.ts
│ │ │ ├── customConstants.ts
│ │ │ ├── customExport.ts
│ │ │ ├── customImport.ts
│ │ │ ├── customInlineDisplay.ts
│ │ │ ├── draftUtils.ts
│ │ │ ├── editor.tsx
│ │ │ ├── fauxSelection.ts
│ │ │ ├── formatters/
│ │ │ │ ├── color.ts
│ │ │ │ ├── convert.ts
│ │ │ │ ├── gradientColor.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── italic.ts
│ │ │ │ ├── letterSpacing.ts
│ │ │ │ ├── test/
│ │ │ │ │ ├── _utils.ts
│ │ │ │ │ ├── color.tsx
│ │ │ │ │ ├── italic.tsx
│ │ │ │ │ ├── letterSpacing.tsx
│ │ │ │ │ ├── underline.tsx
│ │ │ │ │ ├── uppercase.tsx
│ │ │ │ │ └── weight.tsx
│ │ │ │ ├── underline.ts
│ │ │ │ ├── uppercase.ts
│ │ │ │ ├── util.ts
│ │ │ │ └── weight.ts
│ │ │ ├── getFontVariants.ts
│ │ │ ├── getPastedBlocks.ts
│ │ │ ├── getStateInfo.ts
│ │ │ ├── getTextColors.ts
│ │ │ ├── htmlManipulation.ts
│ │ │ ├── index.ts
│ │ │ ├── provider.tsx
│ │ │ ├── styleManipulation.ts
│ │ │ ├── test/
│ │ │ │ ├── getFontVariants.ts
│ │ │ │ ├── getPastedBlocks.ts
│ │ │ │ ├── getTextColors.ts
│ │ │ │ └── styleManipulation.ts
│ │ │ ├── types.ts
│ │ │ ├── typings/
│ │ │ │ └── jest.d.ts
│ │ │ ├── useHandlePastedText.ts
│ │ │ ├── usePasteTextContent.ts
│ │ │ ├── useRichText.ts
│ │ │ ├── useSelectionManipulation.ts
│ │ │ ├── util.ts
│ │ │ └── utils/
│ │ │ ├── getCaretCharacterOffsetWithin.ts
│ │ │ └── getValidHTML.ts
│ │ └── tsconfig.json
│ ├── stickers/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── 12-hours-in-barcelona/
│ │ │ │ ├── index.ts
│ │ │ │ ├── list.tsx
│ │ │ │ ├── tooltip.tsx
│ │ │ │ └── yellowLocationPin.tsx
│ │ │ ├── a-day-in-the-life/
│ │ │ │ ├── alarmClock.tsx
│ │ │ │ ├── brownRice.tsx
│ │ │ │ ├── dumbbells.tsx
│ │ │ │ ├── fish.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── jumpRope.tsx
│ │ │ │ ├── whiteBag.tsx
│ │ │ │ └── yellowLeaves.tsx
│ │ │ ├── ace-hotel-kyoto-review/
│ │ │ │ ├── greenCup.tsx
│ │ │ │ ├── greenCutlery.tsx
│ │ │ │ ├── greenHandBag.tsx
│ │ │ │ └── index.ts
│ │ │ ├── all-about-cars/
│ │ │ │ ├── blueRings.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── multipleBlueRings.tsx
│ │ │ ├── almodos-films/
│ │ │ │ ├── heptagram.tsx
│ │ │ │ └── index.ts
│ │ │ ├── an-artists-legacy/
│ │ │ │ ├── brushStroke.tsx
│ │ │ │ └── index.ts
│ │ │ ├── art-books-gift-guide/
│ │ │ │ ├── books.tsx
│ │ │ │ ├── handHeldSign.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── manReading.tsx
│ │ │ │ ├── openHands.tsx
│ │ │ │ ├── photoFrame.tsx
│ │ │ │ ├── womanReading.tsx
│ │ │ │ └── womanReading02.tsx
│ │ │ ├── baking-bread-guide/
│ │ │ │ ├── breadBun.tsx
│ │ │ │ ├── dough.tsx
│ │ │ │ ├── flourBag.tsx
│ │ │ │ ├── flourBowl.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── jar.tsx
│ │ │ │ ├── thermometer.tsx
│ │ │ │ └── yeastPackage.tsx
│ │ │ ├── beauty-quiz/
│ │ │ │ ├── greenBlob.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── pinkBlob.tsx
│ │ │ │ └── tiltedGreenBlob.tsx
│ │ │ ├── belly-fat-workout/
│ │ │ │ ├── blackSectionSeparator.tsx
│ │ │ │ └── index.ts
│ │ │ ├── buying-art-on-the-internet/
│ │ │ │ ├── blackInstagram.tsx
│ │ │ │ └── index.ts
│ │ │ ├── celebrity-life-story/
│ │ │ │ ├── blackStar.tsx
│ │ │ │ ├── greenStar.tsx
│ │ │ │ └── index.ts
│ │ │ ├── diy-home-office/
│ │ │ │ ├── index.ts
│ │ │ │ └── offWhiteArrow.tsx
│ │ │ ├── doers-get-more-done/
│ │ │ │ ├── facebookIcon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── instagramIcon.tsx
│ │ │ │ ├── orangeCross.tsx
│ │ │ │ ├── orangeDot.tsx
│ │ │ │ ├── plus.tsx
│ │ │ │ ├── rightArrow.tsx
│ │ │ │ ├── twitterIcon.tsx
│ │ │ │ └── youTubeIcon.tsx
│ │ │ ├── elegant-travel-itinerary/
│ │ │ │ ├── floralFrame.tsx
│ │ │ │ ├── floralSeparator.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── stationClock.tsx
│ │ │ │ ├── trainTracks.tsx
│ │ │ │ └── yellowBridge.tsx
│ │ │ ├── experience-thailand/
│ │ │ │ ├── facebookIcon.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── instagramIcon.tsx
│ │ │ │ ├── mapFill.tsx
│ │ │ │ ├── twitterIcon.tsx
│ │ │ │ └── youTubeIcon.tsx
│ │ │ ├── fashion-inspiration/
│ │ │ │ ├── curvedArrow.tsx
│ │ │ │ ├── cutout.tsx
│ │ │ │ └── index.ts
│ │ │ ├── fashion-on-the-go/
│ │ │ │ ├── arrowDark.tsx
│ │ │ │ ├── arrowLight.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── starburst.tsx
│ │ │ │ ├── starburstSolid.tsx
│ │ │ │ └── starburstWithArrow.tsx
│ │ │ ├── fitness-apps-ranked/
│ │ │ │ ├── dumbbells.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── muscle.tsx
│ │ │ │ ├── piechart.tsx
│ │ │ │ ├── running.tsx
│ │ │ │ ├── shoe.tsx
│ │ │ │ └── swimmer.tsx
│ │ │ ├── food-and-stuff/
│ │ │ │ ├── arrow.tsx
│ │ │ │ ├── artichoke.tsx
│ │ │ │ ├── carrot.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── persimmon.tsx
│ │ │ │ ├── radish.tsx
│ │ │ │ └── radishLarge.tsx
│ │ │ ├── fresh-and-bright/
│ │ │ │ ├── cta.tsx
│ │ │ │ ├── heart.tsx
│ │ │ │ └── index.ts
│ │ │ ├── hawaii-travel-packing-list/
│ │ │ │ ├── cartBag.tsx
│ │ │ │ ├── greenLeaf.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── palmLeaf.tsx
│ │ │ │ └── palmTree.tsx
│ │ │ ├── honeymooning-in-italy/
│ │ │ │ ├── floralPattern.tsx
│ │ │ │ └── index.ts
│ │ │ ├── how-contact-tracing-works/
│ │ │ │ ├── index.ts
│ │ │ │ ├── phoneInHand.tsx
│ │ │ │ └── rings.tsx
│ │ │ ├── how-video-calls-saved-the-day/
│ │ │ │ ├── chatBox.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── yellowBrowser.tsx
│ │ │ ├── index.ts
│ │ │ ├── indoor-garden-oasis/
│ │ │ │ ├── curvedScissor.tsx
│ │ │ │ ├── floral.tsx
│ │ │ │ ├── greenBag.tsx
│ │ │ │ ├── greenBulb.tsx
│ │ │ │ ├── greenCurvedLine.tsx
│ │ │ │ ├── greenLightning.tsx
│ │ │ │ ├── greenSun.tsx
│ │ │ │ ├── greenSunLight.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── lengthComparison.tsx
│ │ │ │ ├── lightYellowArrow.tsx
│ │ │ │ ├── scissor.tsx
│ │ │ │ └── waterDroplet.tsx
│ │ │ ├── kitchen-stories/
│ │ │ │ ├── castIron.tsx
│ │ │ │ ├── hotDish.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── oven.tsx
│ │ │ │ └── potatoes.tsx
│ │ │ ├── laptop-buying-guide/
│ │ │ │ ├── index.ts
│ │ │ │ ├── laptopFull.tsx
│ │ │ │ ├── laptopHalf.tsx
│ │ │ │ ├── laptopOff.tsx
│ │ │ │ └── laptopThreeFourth.tsx
│ │ │ ├── los-angeles-city-guide/
│ │ │ │ ├── greenLocationPin.tsx
│ │ │ │ └── index.ts
│ │ │ ├── magazine-article/
│ │ │ │ ├── flightPath.tsx
│ │ │ │ └── index.ts
│ │ │ ├── modernist-travel-guide/
│ │ │ │ ├── index.ts
│ │ │ │ └── linedCircle.tsx
│ │ │ ├── new-york-party-round-up/
│ │ │ │ ├── index.ts
│ │ │ │ ├── instagramIcon.tsx
│ │ │ │ ├── partyCircleText.tsx
│ │ │ │ ├── twitchIcon.tsx
│ │ │ │ └── twitterIcon.tsx
│ │ │ ├── no-days-off/
│ │ │ │ ├── cta.tsx
│ │ │ │ └── index.ts
│ │ │ ├── one-day-city-itinerary/
│ │ │ │ ├── creamSectionSeparator.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── offWhiteLocation.tsx
│ │ │ │ ├── redSectionSeparator.tsx
│ │ │ │ └── whiteLine.tsx
│ │ │ ├── pizzas-in-nyc/
│ │ │ │ ├── arrowRight.tsx
│ │ │ │ ├── cheese.tsx
│ │ │ │ ├── chili.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── mediumBrushStroke.tsx
│ │ │ │ ├── onion.tsx
│ │ │ │ ├── thickBrushStroke.tsx
│ │ │ │ ├── tiltedBrushStroke.tsx
│ │ │ │ ├── tomatoes.tsx
│ │ │ │ └── veggies.tsx
│ │ │ ├── plant-based-dyes/
│ │ │ │ ├── bannerWithDots.tsx
│ │ │ │ ├── greenLeaf.tsx
│ │ │ │ ├── greenLeafShape.tsx
│ │ │ │ ├── greenRoundBanner.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── offWhiteBanner.tsx
│ │ │ │ ├── offWhiteSectionSeparator.tsx
│ │ │ │ ├── plant.tsx
│ │ │ │ ├── roundedBannerWithDots.tsx
│ │ │ │ ├── squigglyLine.tsx
│ │ │ │ ├── wavyLine.tsx
│ │ │ │ ├── yellowDots.tsx
│ │ │ │ ├── yellowLeaf.tsx
│ │ │ │ └── yellowRoundBanner.tsx
│ │ │ ├── rock-music-festival/
│ │ │ │ ├── flames.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── orangeLightning.tsx
│ │ │ │ └── whiteLightning.tsx
│ │ │ ├── sangria-artichoke/
│ │ │ │ ├── curvedArrow.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── openPill.tsx
│ │ │ │ ├── pillBox.tsx
│ │ │ │ ├── pills.tsx
│ │ │ │ ├── scribbledArrow.tsx
│ │ │ │ ├── scribbledUnderline.tsx
│ │ │ │ ├── scribbledUnderline2.tsx
│ │ │ │ └── scribbledUnderlineWhite.tsx
│ │ │ ├── skin-care-at-home/
│ │ │ │ ├── combAndScissors.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── palmIcon.tsx
│ │ │ │ ├── sleepMask.tsx
│ │ │ │ ├── toiletries.tsx
│ │ │ │ ├── towelTurban.tsx
│ │ │ │ └── violetLotus.tsx
│ │ │ ├── sleep/
│ │ │ │ ├── arrowDark.tsx
│ │ │ │ ├── arrowLight.tsx
│ │ │ │ ├── cta.tsx
│ │ │ │ └── index.ts
│ │ │ ├── street-style-on-the-go/
│ │ │ │ ├── index.ts
│ │ │ │ └── tap.tsx
│ │ │ ├── summer-adventure-guide/
│ │ │ │ ├── dashedTrail.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── plus.tsx
│ │ │ │ ├── share.tsx
│ │ │ │ └── terrainMap.tsx
│ │ │ ├── summer-fashion-collection/
│ │ │ │ ├── index.ts
│ │ │ │ ├── yellowHeart.tsx
│ │ │ │ ├── yellowInstagram.tsx
│ │ │ │ └── yellowStar.tsx
│ │ │ ├── sustainability-tips/
│ │ │ │ ├── cloudBanner.tsx
│ │ │ │ └── index.ts
│ │ │ ├── technology-advice/
│ │ │ │ ├── grayFrameCorner.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── whiteFrameCorner.tsx
│ │ │ ├── tips-for-throwing-an-outdoor-luau/
│ │ │ │ ├── greenFlower.tsx
│ │ │ │ ├── greenLeafBanner.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── whiteDottedArrow.tsx
│ │ │ │ ├── yellowFlower.tsx
│ │ │ │ ├── yellowFlowerBanner.tsx
│ │ │ │ └── yellowWavyLine.tsx
│ │ │ ├── tv-show-recap/
│ │ │ │ ├── curvedDottedLine.tsx
│ │ │ │ ├── discPieChart.tsx
│ │ │ │ ├── dottedDiamond.tsx
│ │ │ │ └── index.ts
│ │ │ ├── types.ts
│ │ │ ├── vintage-chairs-what-to-look-for/
│ │ │ │ ├── chair.tsx
│ │ │ │ ├── chair02.tsx
│ │ │ │ └── index.ts
│ │ │ └── weekly-entertainment/
│ │ │ ├── entertainmentStar.tsx
│ │ │ ├── index.ts
│ │ │ └── musicNote.tsx
│ │ └── tsconfig.json
│ ├── stories-block/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── block/
│ │ │ │ ├── block-types/
│ │ │ │ │ ├── latest-stories/
│ │ │ │ │ │ └── edit.js
│ │ │ │ │ ├── selected-stories/
│ │ │ │ │ │ ├── edit.js
│ │ │ │ │ │ └── embedPlaceholder.js
│ │ │ │ │ └── single-story/
│ │ │ │ │ ├── edit.css
│ │ │ │ │ ├── edit.js
│ │ │ │ │ ├── editInLoop.js
│ │ │ │ │ ├── embedControls.js
│ │ │ │ │ ├── embedControlsInLoop.js
│ │ │ │ │ ├── embedLoading.js
│ │ │ │ │ ├── embedPlaceholder.js
│ │ │ │ │ ├── embedPreview.js
│ │ │ │ │ ├── insertFromURLPopover.js
│ │ │ │ │ ├── singleton.js
│ │ │ │ │ ├── storyPlayer.js
│ │ │ │ │ └── test/
│ │ │ │ │ ├── embedLoading.js
│ │ │ │ │ ├── embedPlaceholder.js
│ │ │ │ │ ├── embedPreview.js
│ │ │ │ │ └── storyPlayer.js
│ │ │ │ ├── block.js
│ │ │ │ ├── components/
│ │ │ │ │ ├── authorSelection.js
│ │ │ │ │ ├── autocomplete.js
│ │ │ │ │ ├── blockTypeSwitcher.js
│ │ │ │ │ ├── loaderContainer.js
│ │ │ │ │ ├── storiesBlockConfigurationPanel.js
│ │ │ │ │ ├── storiesBlockControls.js
│ │ │ │ │ ├── storiesInspectorControls.js
│ │ │ │ │ ├── storiesLoading.js
│ │ │ │ │ ├── storiesPreview.js
│ │ │ │ │ ├── storyCard.js
│ │ │ │ │ ├── storyPicker/
│ │ │ │ │ │ ├── fetchSelectedStories.js
│ │ │ │ │ │ ├── itemOverlay.js
│ │ │ │ │ │ ├── selectStories.js
│ │ │ │ │ │ ├── sortStories.js
│ │ │ │ │ │ ├── storyPicker.js
│ │ │ │ │ │ └── storyPreview.js
│ │ │ │ │ ├── taxonomyItem.js
│ │ │ │ │ └── test/
│ │ │ │ │ ├── blockTypeSwitcher.js
│ │ │ │ │ ├── loaderContainer.js
│ │ │ │ │ └── storyCard.js
│ │ │ │ ├── constants.js
│ │ │ │ ├── deprecated.js
│ │ │ │ ├── edit.css
│ │ │ │ ├── edit.js
│ │ │ │ ├── icons.js
│ │ │ │ ├── index.js
│ │ │ │ ├── save.js
│ │ │ │ ├── test/
│ │ │ │ │ ├── autocomplete.js
│ │ │ │ │ ├── block.js
│ │ │ │ │ ├── save.js
│ │ │ │ │ └── storiesPlaceholder.js
│ │ │ │ └── transforms.js
│ │ │ ├── css/
│ │ │ │ ├── common.css
│ │ │ │ ├── core-themes/
│ │ │ │ │ ├── twentyeleven.css
│ │ │ │ │ ├── twentyfifteen.css
│ │ │ │ │ ├── twentyfourteen.css
│ │ │ │ │ ├── twentyseventeen.css
│ │ │ │ │ ├── twentysixteen.css
│ │ │ │ │ ├── twentyten.css
│ │ │ │ │ ├── twentytwelve.css
│ │ │ │ │ ├── twentytwenty.css
│ │ │ │ │ └── twentytwentyone.css
│ │ │ │ ├── embed.css
│ │ │ │ ├── lightbox.css
│ │ │ │ ├── singleton.css
│ │ │ │ ├── style.css
│ │ │ │ ├── variables.css
│ │ │ │ └── views/
│ │ │ │ ├── carousel.css
│ │ │ │ ├── circles.css
│ │ │ │ ├── grid.css
│ │ │ │ └── list.css
│ │ │ ├── index.js
│ │ │ ├── publicPath.js
│ │ │ └── view.ts
│ │ └── tsconfig.json
│ ├── stories-carousel/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── @types/
│ │ │ │ └── global.d.ts
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── story-editor/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── api/
│ │ │ │ │ ├── apiProvider.tsx
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ └── apiProvider.js
│ │ │ │ │ └── useAPI.ts
│ │ │ │ ├── canvas/
│ │ │ │ │ ├── canvasProvider.tsx
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── useAddPastedElements.ts
│ │ │ │ │ ├── useCanvas.ts
│ │ │ │ │ ├── useCanvasBoundingBox.ts
│ │ │ │ │ ├── useCanvasCopyPaste.ts
│ │ │ │ │ ├── useCanvasKeys.ts
│ │ │ │ │ ├── useEditingElement.ts
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── getLayerArrangementProps.ts
│ │ │ │ │ └── test/
│ │ │ │ │ └── getLayerArrangementProps.js
│ │ │ │ ├── config/
│ │ │ │ │ ├── configProvider.tsx
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useConfig.ts
│ │ │ │ ├── currentUser/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── currentUserProvider.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── useCurrentUser.ts
│ │ │ │ ├── font/
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ └── useLoadFontFiles.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── fontProvider.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── actions/
│ │ │ │ │ │ └── useLoadFontFiles.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── useFont.ts
│ │ │ │ ├── helpCenter/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── provider.tsx
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── useHelpCenter/
│ │ │ │ │ │ ├── effects.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ ├── effects.ts
│ │ │ │ │ │ └── useHelpCenter.tsx
│ │ │ │ │ └── useHelpCenterReducer.ts
│ │ │ │ ├── highlights/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── provider.tsx
│ │ │ │ │ ├── states.ts
│ │ │ │ │ ├── styles.js
│ │ │ │ │ └── useHighlights.ts
│ │ │ │ ├── history/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── historyProvider.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── history.karma.js
│ │ │ │ │ ├── reducer.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── reducer.js
│ │ │ │ │ ├── useHistory.ts
│ │ │ │ │ └── useHistoryReducer.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── layout/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── layoutProvider.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── useZoomSetting.js
│ │ │ │ │ ├── useCarouselDrawer.ts
│ │ │ │ │ ├── useLayout.ts
│ │ │ │ │ └── useZoomSetting.ts
│ │ │ │ ├── media/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── local/
│ │ │ │ │ │ ├── actions.js
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ ├── reducers/
│ │ │ │ │ │ │ ├── addAudioProcessing.js
│ │ │ │ │ │ │ ├── addPosterProcessing.js
│ │ │ │ │ │ │ ├── fetchMedia.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── prependMedia.js
│ │ │ │ │ │ │ ├── removeAudioProcessing.js
│ │ │ │ │ │ │ ├── removePosterProcessing.js
│ │ │ │ │ │ │ ├── resetFilters.js
│ │ │ │ │ │ │ ├── setMedia.js
│ │ │ │ │ │ │ ├── setMediaType.js
│ │ │ │ │ │ │ ├── setSearchTerm.js
│ │ │ │ │ │ │ └── setupState.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ │ ├── useContextValueProvider.js
│ │ │ │ │ │ │ └── useLocalMedia.js
│ │ │ │ │ │ ├── typedefs.js
│ │ │ │ │ │ ├── types.js
│ │ │ │ │ │ ├── useContextValueProvider.js
│ │ │ │ │ │ └── useLocalMedia.js
│ │ │ │ │ ├── media3p/
│ │ │ │ │ │ ├── actions.js
│ │ │ │ │ │ ├── api/
│ │ │ │ │ │ │ ├── apiFetcher.js
│ │ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── media3pApiProvider.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── apiFetcher.js
│ │ │ │ │ │ │ │ └── useMedia3pApi.js
│ │ │ │ │ │ │ ├── typedefs.js
│ │ │ │ │ │ │ └── useMedia3pApi.js
│ │ │ │ │ │ ├── attribution.js
│ │ │ │ │ │ ├── categories/
│ │ │ │ │ │ │ ├── actions.js
│ │ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── reducer.js
│ │ │ │ │ │ │ ├── typedefs.js
│ │ │ │ │ │ │ └── types.js
│ │ │ │ │ │ ├── providerConfiguration.js
│ │ │ │ │ │ ├── providerReducer.js
│ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── providerReducer.js
│ │ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ │ ├── useContextValueProvider.js
│ │ │ │ │ │ │ ├── useFetchCategoriesEffect.js
│ │ │ │ │ │ │ └── useFetchMediaEffect.js
│ │ │ │ │ │ ├── typedefs.js
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ ├── useContextValueProvider.js
│ │ │ │ │ │ ├── useFetchCategoriesEffect.js
│ │ │ │ │ │ ├── useFetchMediaEffect.js
│ │ │ │ │ │ └── useProviderContextValueProvider.js
│ │ │ │ │ ├── mediaProvider.js
│ │ │ │ │ ├── pagination/
│ │ │ │ │ │ ├── actions.js
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── reducer.js
│ │ │ │ │ │ └── types.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── useMediaReducer.js
│ │ │ │ │ │ └── useUploadMedia.js
│ │ │ │ │ ├── typedefs.js
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── uploadQueue/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── reducer.ts
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ │ └── useMediaUploadQueue.js
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ ├── useMediaUploadQueue.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── useMedia.js
│ │ │ │ │ ├── useMediaReducer.js
│ │ │ │ │ ├── useUploadMedia.js
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── getPosterName.ts
│ │ │ │ │ ├── getResourceFromLocalFile.ts
│ │ │ │ │ ├── getResourceFromMedia3p.js
│ │ │ │ │ ├── getResourceFromUrl.ts
│ │ │ │ │ ├── heif/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── useConvertHeif.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── getResourceFromMedia3p.js
│ │ │ │ │ │ ├── useFFmpeg.js
│ │ │ │ │ │ ├── useMediaInfo.tsx
│ │ │ │ │ │ └── useProcessMedia.js
│ │ │ │ │ ├── useDetectBaseColor.ts
│ │ │ │ │ ├── useDetectBlurhash.js
│ │ │ │ │ ├── useDetectVideoHasAudio.ts
│ │ │ │ │ ├── useFFmpeg.ts
│ │ │ │ │ ├── useMediaInfo.ts
│ │ │ │ │ ├── useProcessMedia.ts
│ │ │ │ │ ├── useUpdateElementDimensions.ts
│ │ │ │ │ ├── useUploadVideoFrame.ts
│ │ │ │ │ └── useVideoElementTranscoding.js
│ │ │ │ ├── pageCanvas/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── getPageWithoutSelection.ts
│ │ │ │ │ ├── getPixelDataFromCanvas.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── pageCanvasCacheValidator.ts
│ │ │ │ │ ├── pageCanvasProvider.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── usePageCanvas.js
│ │ │ │ │ ├── testUtils/
│ │ │ │ │ │ ├── createMockPage.js
│ │ │ │ │ │ └── useStoryMock.js
│ │ │ │ │ ├── useCalculateAccessibleTextColors.ts
│ │ │ │ │ ├── usePageCanvas.ts
│ │ │ │ │ ├── usePageCanvasMap.ts
│ │ │ │ │ ├── usePageSnapshot.ts
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── storyPageToCanvas.ts
│ │ │ │ │ ├── storyPageToDataUrl.ts
│ │ │ │ │ └── storyPageToNode.tsx
│ │ │ │ ├── pageDataUrls/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── pageDataUrlsProvider.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── usePageDataUrls.js
│ │ │ │ │ └── usePageDataUrls.ts
│ │ │ │ ├── quickActions/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── mediaPicker.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── useQuickActions.js
│ │ │ │ │ ├── useElementReset.js
│ │ │ │ │ ├── useForegroundActions.js
│ │ │ │ │ ├── useMediaActions.js
│ │ │ │ │ ├── useQuickActions.js
│ │ │ │ │ ├── useTextActions.js
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── getResetProperties.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── getResetProperties.js
│ │ │ │ ├── rightClickMenu/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── hooks/
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── testUtils.js
│ │ │ │ │ │ │ ├── useCopyPasteActions.js
│ │ │ │ │ │ │ ├── useElementActions.js
│ │ │ │ │ │ │ ├── useLayerActions.js
│ │ │ │ │ │ │ ├── usePageActions.js
│ │ │ │ │ │ │ └── usePresetActions.js
│ │ │ │ │ │ ├── useCopyPasteActions.js
│ │ │ │ │ │ ├── useElementActions.js
│ │ │ │ │ │ ├── useHeadingSelect.js
│ │ │ │ │ │ ├── useLayerActions.js
│ │ │ │ │ │ ├── usePageActions.js
│ │ │ │ │ │ └── usePresetActions.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── items/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── layerHide.js
│ │ │ │ │ │ ├── layerLock.js
│ │ │ │ │ │ ├── layerName.js
│ │ │ │ │ │ └── layerUngroup.js
│ │ │ │ │ ├── menus/
│ │ │ │ │ │ ├── emptyStateMenu.js
│ │ │ │ │ │ ├── foregroundMediaMenu.js
│ │ │ │ │ │ ├── groupMenu.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── multipleElementsMenu.js
│ │ │ │ │ │ ├── pageMenu.js
│ │ │ │ │ │ ├── productMenu.js
│ │ │ │ │ │ ├── shapeMenu.js
│ │ │ │ │ │ ├── shared.js
│ │ │ │ │ │ ├── stickerMenu.js
│ │ │ │ │ │ └── textMenu.js
│ │ │ │ │ ├── provider.js
│ │ │ │ │ ├── reducer.js
│ │ │ │ │ ├── useLayerSelect.js
│ │ │ │ │ └── useRightClickMenu.js
│ │ │ │ ├── story/
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── useAutoSave.js
│ │ │ │ │ │ ├── useAutoSave.ts
│ │ │ │ │ │ ├── useLocalAutoSave.ts
│ │ │ │ │ │ └── useSaveStory.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── effects/
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── useHashState.js
│ │ │ │ │ │ │ └── useLoadStory.js
│ │ │ │ │ │ ├── useHashState.ts
│ │ │ │ │ │ ├── useHistoryEntry.ts
│ │ │ │ │ │ ├── useHistoryReplay.ts
│ │ │ │ │ │ └── useLoadStory.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── storyProvider.tsx
│ │ │ │ │ ├── storyTriggers/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── storyEvents/
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── onInitialElementAddedRegister.ts
│ │ │ │ │ │ │ ├── onPageAddedRegister.ts
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── onInitialElementAddedRegister.js
│ │ │ │ │ │ │ │ └── onPageAddedRegister.js
│ │ │ │ │ │ │ └── types.ts
│ │ │ │ │ │ ├── storyTriggersProvider.tsx
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── useStoryTriggers.js
│ │ │ │ │ │ └── useStoryTriggers.ts
│ │ │ │ │ ├── useStory.ts
│ │ │ │ │ ├── useStoryReducer/
│ │ │ │ │ │ ├── actions.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── reducer.ts
│ │ │ │ │ │ ├── reducers/
│ │ │ │ │ │ │ ├── addAnimations.ts
│ │ │ │ │ │ │ ├── addElements.ts
│ │ │ │ │ │ │ ├── addElementsAcrossPages.ts
│ │ │ │ │ │ │ ├── addGroup.ts
│ │ │ │ │ │ │ ├── addPage.ts
│ │ │ │ │ │ │ ├── arrangeElement.ts
│ │ │ │ │ │ │ ├── arrangeGroup.ts
│ │ │ │ │ │ │ ├── arrangePage.ts
│ │ │ │ │ │ │ ├── combineElements.ts
│ │ │ │ │ │ │ ├── copySelectedElement.ts
│ │ │ │ │ │ │ ├── deleteElements.ts
│ │ │ │ │ │ │ ├── deleteElementsByResourceId.ts
│ │ │ │ │ │ │ ├── deleteGroup.ts
│ │ │ │ │ │ │ ├── deletePage.ts
│ │ │ │ │ │ │ ├── duplicateElementsById.ts
│ │ │ │ │ │ │ ├── duplicateGroup.ts
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── removeElementFromGroup.ts
│ │ │ │ │ │ │ ├── restore.ts
│ │ │ │ │ │ │ ├── selectElement.ts
│ │ │ │ │ │ │ ├── setBackgroundElement.ts
│ │ │ │ │ │ │ ├── setCurrentPage.ts
│ │ │ │ │ │ │ ├── setSelectedElements.ts
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ │ ├── toggleElement.ts
│ │ │ │ │ │ │ ├── toggleLayer.ts
│ │ │ │ │ │ │ ├── unselectElement.ts
│ │ │ │ │ │ │ ├── updateAnimationState.ts
│ │ │ │ │ │ │ ├── updateElements.ts
│ │ │ │ │ │ │ ├── updateElementsByFontFamily.ts
│ │ │ │ │ │ │ ├── updateElementsByResourceId.ts
│ │ │ │ │ │ │ ├── updateGroup.ts
│ │ │ │ │ │ │ ├── updatePage.ts
│ │ │ │ │ │ │ ├── updateStory.ts
│ │ │ │ │ │ │ └── utils.ts
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ │ ├── addAnimations.js
│ │ │ │ │ │ │ ├── addElement.js
│ │ │ │ │ │ │ ├── addElementToSelection.js
│ │ │ │ │ │ │ ├── addElements.js
│ │ │ │ │ │ │ ├── addElementsAcrossPages.js
│ │ │ │ │ │ │ ├── addGroup.js
│ │ │ │ │ │ │ ├── addPage.js
│ │ │ │ │ │ │ ├── addPageAt.js
│ │ │ │ │ │ │ ├── arrangeElement.js
│ │ │ │ │ │ │ ├── arrangeGroup.js
│ │ │ │ │ │ │ ├── arrangePage.js
│ │ │ │ │ │ │ ├── arrangeSelection.js
│ │ │ │ │ │ │ ├── clearBackgroundElement.js
│ │ │ │ │ │ │ ├── clearSelection.js
│ │ │ │ │ │ │ ├── combineElements.js
│ │ │ │ │ │ │ ├── copySelectedElement.js
│ │ │ │ │ │ │ ├── deleteCurrentPage.js
│ │ │ │ │ │ │ ├── deleteElementById.js
│ │ │ │ │ │ │ ├── deleteElementsById.js
│ │ │ │ │ │ │ ├── deleteElementsByResourceId.js
│ │ │ │ │ │ │ ├── deleteGroupAndElementsById.js
│ │ │ │ │ │ │ ├── deleteGroupById.js
│ │ │ │ │ │ │ ├── deletePage.js
│ │ │ │ │ │ │ ├── deleteSelectedElements.js
│ │ │ │ │ │ │ ├── duplicateElementsById.js
│ │ │ │ │ │ │ ├── duplicateGroupById.js
│ │ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ │ ├── removeElementFromGroup.js
│ │ │ │ │ │ │ ├── removeElementFromSelection.js
│ │ │ │ │ │ │ ├── restore.js
│ │ │ │ │ │ │ ├── setBackgroundElement.js
│ │ │ │ │ │ │ ├── setCurrentPage.js
│ │ │ │ │ │ │ ├── setSelectedElementsById.js
│ │ │ │ │ │ │ ├── toggleElementInSelection.js
│ │ │ │ │ │ │ ├── toggleLayer.js
│ │ │ │ │ │ │ ├── updateAnimationState.js
│ │ │ │ │ │ │ ├── updateCurrentPageProperties.js
│ │ │ │ │ │ │ ├── updateElementById.js
│ │ │ │ │ │ │ ├── updateElementsByFontFamily.js
│ │ │ │ │ │ │ ├── updateElementsById.js
│ │ │ │ │ │ │ ├── updateElementsByResourceId.js
│ │ │ │ │ │ │ ├── updateGroupById.js
│ │ │ │ │ │ │ ├── updatePageProperties.js
│ │ │ │ │ │ │ ├── updateSelectedElements.js
│ │ │ │ │ │ │ └── updateStory.js
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ └── useStoryReducer.ts
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── cleanElementFontProperties.ts
│ │ │ │ │ ├── deleteNestedKeys.ts
│ │ │ │ │ ├── getAllProducts.ts
│ │ │ │ │ ├── getStoryFontsFromPages.ts
│ │ │ │ │ ├── getStoryPropsToSave.ts
│ │ │ │ │ ├── isEmptyStory.ts
│ │ │ │ │ ├── pageContainsBlobUrl.ts
│ │ │ │ │ └── test/
│ │ │ │ │ ├── cleanElementFontPropties.js
│ │ │ │ │ ├── deleteNestedKeys.js
│ │ │ │ │ ├── getAllProduct.js
│ │ │ │ │ ├── getStoryFontsFromPages.js
│ │ │ │ │ ├── getStoryPropsToSave.js
│ │ │ │ │ ├── isEmptyStory.js
│ │ │ │ │ └── pageContainsBlobUrl.js
│ │ │ │ ├── taxonomy/
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── taxonomyProvider.tsx
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── useTaxonomy.js
│ │ │ │ │ └── useTaxonomy.ts
│ │ │ │ ├── uploader/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── useUploader.js
│ │ │ │ │ └── useUploader.ts
│ │ │ │ └── userOnboarding/
│ │ │ │ ├── index.js
│ │ │ │ ├── test/
│ │ │ │ │ └── useUserOnboarding.js
│ │ │ │ └── useUserOnboarding.js
│ │ │ ├── components/
│ │ │ │ ├── autoSaveCheck/
│ │ │ │ │ ├── autoSaveDialog.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── autoSaveDialog.js
│ │ │ │ ├── autoSaveHandler/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── autoSaveHandler.js
│ │ │ │ ├── canvas/
│ │ │ │ │ ├── canvas.js
│ │ │ │ │ ├── canvasElementDropzone.js
│ │ │ │ │ ├── canvasLayout.js
│ │ │ │ │ ├── canvasUploadDropTarget.js
│ │ │ │ │ ├── displayElement.d.ts
│ │ │ │ │ ├── displayElement.js
│ │ │ │ │ ├── displayLayer.js
│ │ │ │ │ ├── editElement.js
│ │ │ │ │ ├── editLayer.js
│ │ │ │ │ ├── editLayerFocusManager/
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── keyBindings.js
│ │ │ │ │ │ ├── provider.js
│ │ │ │ │ │ ├── reduction.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── EditLayerFocusManager.js
│ │ │ │ │ │ ├── useEditLayerFocusManager.js
│ │ │ │ │ │ └── useFocusGroupRef.js
│ │ │ │ │ ├── emptyStateLayer.js
│ │ │ │ │ ├── extraPages.js
│ │ │ │ │ ├── eyedropperLayer.js
│ │ │ │ │ ├── frameElement.js
│ │ │ │ │ ├── framesLayer.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── backgroundCopyPaste.karma.js
│ │ │ │ │ │ ├── canvasKeyboardNavigation.karma.js
│ │ │ │ │ │ ├── canvasKeys.karma.js
│ │ │ │ │ │ ├── carousel.karma.js
│ │ │ │ │ │ ├── cloneSelection.karma.js
│ │ │ │ │ │ ├── elementKeyboardNavigation.js
│ │ │ │ │ │ ├── fullbleedMediaAsBackground.karma.js
│ │ │ │ │ │ ├── keys.karma.js
│ │ │ │ │ │ ├── lasso.karma.js
│ │ │ │ │ │ ├── multiSelectionMovable.karma.js
│ │ │ │ │ │ ├── pageMenuActions.karma.js
│ │ │ │ │ │ ├── pageSideMenuActions.karma.js
│ │ │ │ │ │ ├── quickActions.karma.js
│ │ │ │ │ │ ├── rightClickMenu.karma.js
│ │ │ │ │ │ ├── rtl.karma.js
│ │ │ │ │ │ ├── selection.karma.js
│ │ │ │ │ │ └── snapping.karma.js
│ │ │ │ │ ├── layout.js
│ │ │ │ │ ├── mediaCaptions/
│ │ │ │ │ │ ├── cue.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── mediaCaptionsLayer.js
│ │ │ │ │ │ ├── parseTimestamp.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── parseTimestamp.js
│ │ │ │ │ │ └── trackRenderer.js
│ │ │ │ │ ├── mediaRecordingLayer.js
│ │ │ │ │ ├── multiSelectionMoveable/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── useDrag.js
│ │ │ │ │ │ ├── useResize.js
│ │ │ │ │ │ └── useRotate.js
│ │ │ │ │ ├── navLayer.js
│ │ │ │ │ ├── pageAttachment/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ └── pageAttachment.cuj.karma.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── pageAttachment.js
│ │ │ │ │ ├── pageSideMenu.js
│ │ │ │ │ ├── pagemenu/
│ │ │ │ │ │ ├── animationToggle.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── pageMenu.js
│ │ │ │ │ │ └── pageMenuButton.js
│ │ │ │ │ ├── pagenav/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── renderResourcePlaceholder.js
│ │ │ │ │ ├── rightClickMenu.js
│ │ │ │ │ ├── selection.js
│ │ │ │ │ ├── selectionCanvas.js
│ │ │ │ │ ├── shoppingPageAttachment/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── singleSelectionMoveable/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── useDrag.js
│ │ │ │ │ │ ├── useResize.js
│ │ │ │ │ │ └── useRotate.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── __snapshots__/
│ │ │ │ │ │ │ └── mediaDisplay.js.snap
│ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ ├── frame.js
│ │ │ │ │ │ ├── frameElement.js
│ │ │ │ │ │ ├── mediaDisplay.js
│ │ │ │ │ │ ├── multiSelectionMoveable.js
│ │ │ │ │ │ ├── singleSelectionMoveable.js
│ │ │ │ │ │ ├── useCanvasKeys.js
│ │ │ │ │ │ └── useInsertElement.js
│ │ │ │ │ ├── useFocusCanvas.ts
│ │ │ │ │ ├── useInsertElement.ts
│ │ │ │ │ ├── useInsertTextSet.js
│ │ │ │ │ ├── usePinchToZoom.js
│ │ │ │ │ ├── useUploadWithPreview.d.ts
│ │ │ │ │ ├── useUploadWithPreview.js
│ │ │ │ │ ├── useWindowResizeHandler.js
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── getColorFromPixelData.js
│ │ │ │ │ ├── getElementProperties.ts
│ │ │ │ │ ├── normalizeRotationDegrees.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── getElementProperties.js
│ │ │ │ │ ├── useElementOutOfCanvas.js
│ │ │ │ │ ├── useFullbleedMediaAsBackground.js
│ │ │ │ │ ├── useSnapping.js
│ │ │ │ │ └── useUpdateSelectionRectangle.js
│ │ │ │ ├── checklist/
│ │ │ │ │ ├── checklist.js
│ │ │ │ │ ├── checklistContent/
│ │ │ │ │ │ ├── accessibilityChecks.js
│ │ │ │ │ │ ├── designChecks.js
│ │ │ │ │ │ ├── emptyContent.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── priorityChecks.js
│ │ │ │ │ ├── checklistContext/
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── provider.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── useChecklist.js
│ │ │ │ │ │ └── useChecklist.js
│ │ │ │ │ ├── checklistIcon.js
│ │ │ │ │ ├── checkpointContext/
│ │ │ │ │ │ ├── checkpointContext.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── checks/
│ │ │ │ │ │ ├── elementLinkTappableRegionTooBig.js
│ │ │ │ │ │ ├── elementLinkTappableRegionTooSmall.js
│ │ │ │ │ │ ├── firstPageAnimation.js
│ │ │ │ │ │ ├── imageElementMissingAlt.js
│ │ │ │ │ │ ├── imageElementResolution.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── pageBackgroundLowTextContrast/
│ │ │ │ │ │ │ ├── check.js
│ │ │ │ │ │ │ ├── component.js
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── pageTooLittleText.js
│ │ │ │ │ │ ├── pageTooManyLinks.js
│ │ │ │ │ │ ├── pageTooMuchText.js
│ │ │ │ │ │ ├── publisherLogoMissing.js
│ │ │ │ │ │ ├── publisherLogoSize.js
│ │ │ │ │ │ ├── shared/
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── thumbnailWrapper.js
│ │ │ │ │ │ │ ├── thumbnailWrapper.js
│ │ │ │ │ │ │ └── videoChecklistCard.js
│ │ │ │ │ │ ├── storyAmpValidationErrors.js
│ │ │ │ │ │ ├── storyMissingExcerpt.js
│ │ │ │ │ │ ├── storyMissingTitle.js
│ │ │ │ │ │ ├── storyPagesCount.js
│ │ │ │ │ │ ├── storyPosterAttached.js
│ │ │ │ │ │ ├── storyPosterSize.js
│ │ │ │ │ │ ├── storyTitleLength.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── elementLinkTappableRegionTooBig.js
│ │ │ │ │ │ │ ├── elementLinkTappableRegionTooSmall.js
│ │ │ │ │ │ │ ├── firstPageAnimation.js
│ │ │ │ │ │ │ ├── imageElementMissingAlt.js
│ │ │ │ │ │ │ ├── imageElementResolution.js
│ │ │ │ │ │ │ ├── pageBackgroundLowTextContrast.js
│ │ │ │ │ │ │ ├── pageTooLittleText.js
│ │ │ │ │ │ │ ├── pageTooManyLinks.js
│ │ │ │ │ │ │ ├── pageTooMuchText.js
│ │ │ │ │ │ │ ├── publisherLogoMissing.js
│ │ │ │ │ │ │ ├── publisherLogoSize.js
│ │ │ │ │ │ │ ├── storyAmpValidationErrors.js
│ │ │ │ │ │ │ ├── storyMissingExcerpt.js
│ │ │ │ │ │ │ ├── storyMissingTitle.js
│ │ │ │ │ │ │ ├── storyPagesCount.js
│ │ │ │ │ │ │ ├── storyPosterAttached.js
│ │ │ │ │ │ │ ├── storyPosterSize.js
│ │ │ │ │ │ │ ├── storyTitleLength.js
│ │ │ │ │ │ │ ├── textElementFontSizeTooSmall.js
│ │ │ │ │ │ │ ├── videoElementLength.js
│ │ │ │ │ │ │ ├── videoElementMissingCaptions.js
│ │ │ │ │ │ │ ├── videoElementMissingDescription.js
│ │ │ │ │ │ │ ├── videoElementMissingPoster.js
│ │ │ │ │ │ │ ├── videoElementResolution.js
│ │ │ │ │ │ │ └── videoOptimization.js
│ │ │ │ │ │ ├── textElementFontSizeTooSmall.js
│ │ │ │ │ │ ├── videoElementLength.js
│ │ │ │ │ │ ├── videoElementMissingCaptions.js
│ │ │ │ │ │ ├── videoElementMissingDescription.js
│ │ │ │ │ │ ├── videoElementMissingPoster.js
│ │ │ │ │ │ ├── videoElementResolution.js
│ │ │ │ │ │ └── videoOptimization.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── countContext/
│ │ │ │ │ │ ├── checkCountContext.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── checkCountContext.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── checklist.karma.js
│ │ │ │ │ │ ├── firstPageAnimation.karma.js
│ │ │ │ │ │ └── prepublishSelect.karma.js
│ │ │ │ │ ├── popupMountedContext.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styles.js
│ │ │ │ │ ├── toggle/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── characterCountForPage.js
│ │ │ │ │ ├── filterStoryElements.js
│ │ │ │ │ ├── filterStoryPages.js
│ │ │ │ │ ├── getVisibleThumbnails.js
│ │ │ │ │ ├── hasNoFeaturedMedia.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── filterStoryElements.js
│ │ │ │ │ │ └── filterStoryPages.js
│ │ │ │ │ └── thumbnailPagePreview.js
│ │ │ │ ├── checklistCard/
│ │ │ │ │ ├── checkboxCta.js
│ │ │ │ │ ├── checklistCard.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── defaultCtaButton.js
│ │ │ │ │ ├── defaultFooterText.js
│ │ │ │ │ ├── helpers/
│ │ │ │ │ │ ├── getGridVariant.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── styles.js
│ │ │ │ ├── colorPicker/
│ │ │ │ │ ├── addCustomColor.js
│ │ │ │ │ ├── basicColorList.js
│ │ │ │ │ ├── basicColorPicker.js
│ │ │ │ │ ├── colorAdd.js
│ │ │ │ │ ├── colorPicker.js
│ │ │ │ │ ├── confirmationDialog.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── currentColorPicker.js
│ │ │ │ │ ├── customColorPicker.js
│ │ │ │ │ ├── editablePreview.js
│ │ │ │ │ ├── gradientLine.js
│ │ │ │ │ ├── gradientPicker.js
│ │ │ │ │ ├── gradientStop.js
│ │ │ │ │ ├── header.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── insertStop.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── colorPicker.karma.js
│ │ │ │ │ │ └── eyedropper.karma.js
│ │ │ │ │ ├── patternTypePicker.js
│ │ │ │ │ ├── pointer.js
│ │ │ │ │ ├── regenerateColor.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── colorPicker/
│ │ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ │ ├── addStopByPointer.js
│ │ │ │ │ │ │ ├── colorInteraction.js
│ │ │ │ │ │ │ ├── footerInteraction.js
│ │ │ │ │ │ │ ├── headerInteraction.js
│ │ │ │ │ │ │ ├── manipulateGradient.js
│ │ │ │ │ │ │ ├── manipulateStopByKeyboard.js
│ │ │ │ │ │ │ ├── moveStopByPointer.js
│ │ │ │ │ │ │ ├── onclose.js
│ │ │ │ │ │ │ ├── onload.js
│ │ │ │ │ │ │ ├── savedColors.js
│ │ │ │ │ │ │ └── selectStop.js
│ │ │ │ │ │ ├── insertStop.js
│ │ │ │ │ │ ├── regenerateColor.js
│ │ │ │ │ │ └── useColor/
│ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ ├── addStopAt.js
│ │ │ │ │ │ ├── load.js
│ │ │ │ │ │ ├── moveCurrentStopBy.js
│ │ │ │ │ │ ├── removeCurrentStop.js
│ │ │ │ │ │ ├── reverseStops.js
│ │ │ │ │ │ ├── rotateClockwise.js
│ │ │ │ │ │ ├── selectStop.js
│ │ │ │ │ │ ├── setToGradient.js
│ │ │ │ │ │ ├── setToSolid.js
│ │ │ │ │ │ └── updateCurrentColor.js
│ │ │ │ │ ├── useColor.js
│ │ │ │ │ ├── useDeleteColor.js
│ │ │ │ │ ├── useKeyAddStop.js
│ │ │ │ │ ├── useKeyDeleteStop.js
│ │ │ │ │ ├── useKeyFocus.js
│ │ │ │ │ ├── useKeyMoveStop.js
│ │ │ │ │ ├── usePointerAddStop.js
│ │ │ │ │ ├── usePointerMoveStop.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── devTools/
│ │ │ │ │ ├── devTools.js
│ │ │ │ │ ├── dummyData.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── dialog/
│ │ │ │ │ ├── dialog.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── directionAware/
│ │ │ │ │ └── index.js
│ │ │ │ ├── dropTargets/
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── dropTarget.karma.js
│ │ │ │ │ │ └── order.karma.js
│ │ │ │ │ ├── provider.js
│ │ │ │ │ └── useDropTargets.js
│ │ │ │ ├── elementLink/
│ │ │ │ │ ├── frame.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── emptyContentMessage.js
│ │ │ │ ├── errorBoundary/
│ │ │ │ │ ├── copyStoryDataToClipboard.js
│ │ │ │ │ ├── errorActions.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── eyedropper/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── useEyeDropperApi.js
│ │ │ │ ├── floatingMenu/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── context/
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── provider.js
│ │ │ │ │ │ └── use.js
│ │ │ │ │ ├── elements/
│ │ │ │ │ │ ├── borderRadius.js
│ │ │ │ │ │ ├── borderWidthAndColor.js
│ │ │ │ │ │ ├── dismiss.js
│ │ │ │ │ │ ├── elementAlignment.js
│ │ │ │ │ │ ├── flipHorizontal.js
│ │ │ │ │ │ ├── flipVertical.js
│ │ │ │ │ │ ├── fontFamily.js
│ │ │ │ │ │ ├── fontSize.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ ├── border.karma.js
│ │ │ │ │ │ │ ├── borderRadius.karma.js
│ │ │ │ │ │ │ ├── flip.karma.js
│ │ │ │ │ │ │ ├── loop.karma.js
│ │ │ │ │ │ │ ├── more.karma.js
│ │ │ │ │ │ │ ├── opacity.karma.js
│ │ │ │ │ │ │ ├── shopping.karma.js
│ │ │ │ │ │ │ ├── text.karma.js
│ │ │ │ │ │ │ └── textAlign.karma.js
│ │ │ │ │ │ ├── layerOpacity.js
│ │ │ │ │ │ ├── loop.js
│ │ │ │ │ │ ├── more.js
│ │ │ │ │ │ ├── mute.js
│ │ │ │ │ │ ├── settings.js
│ │ │ │ │ │ ├── shapeColor.js
│ │ │ │ │ │ ├── shared/
│ │ │ │ │ │ │ ├── color.js
│ │ │ │ │ │ │ ├── focusTrapButton.js
│ │ │ │ │ │ │ ├── icon.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── input.js
│ │ │ │ │ │ │ ├── separator.js
│ │ │ │ │ │ │ ├── text.js
│ │ │ │ │ │ │ ├── toggleButton.js
│ │ │ │ │ │ │ ├── useFlip.ts
│ │ │ │ │ │ │ ├── useProperties.ts
│ │ │ │ │ │ │ └── useTextToggle.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── mute.js
│ │ │ │ │ │ │ └── trim.js
│ │ │ │ │ │ ├── textAlign.js
│ │ │ │ │ │ ├── textColor.js
│ │ │ │ │ │ ├── toggleBold.js
│ │ │ │ │ │ ├── toggleItalics.js
│ │ │ │ │ │ ├── toggleUnderline.js
│ │ │ │ │ │ ├── trash.js
│ │ │ │ │ │ └── trim.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── floatingMenu.karma.js
│ │ │ │ │ │ ├── image.karma.js
│ │ │ │ │ │ ├── shape.karma.js
│ │ │ │ │ │ ├── sticker.karma.js
│ │ │ │ │ │ ├── text.karma.js
│ │ │ │ │ │ ├── utils.js
│ │ │ │ │ │ └── video.karma.js
│ │ │ │ │ ├── layer.js
│ │ │ │ │ ├── menu.js
│ │ │ │ │ ├── menus/
│ │ │ │ │ │ ├── audioSticker.js
│ │ │ │ │ │ ├── image.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── multiple.js
│ │ │ │ │ │ ├── product.js
│ │ │ │ │ │ ├── selector.js
│ │ │ │ │ │ ├── shape.js
│ │ │ │ │ │ ├── sticker.js
│ │ │ │ │ │ ├── text.js
│ │ │ │ │ │ └── video.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── fontPicker/
│ │ │ │ │ └── index.js
│ │ │ │ ├── footer/
│ │ │ │ │ ├── carousel/
│ │ │ │ │ │ ├── carouselContainer.js
│ │ │ │ │ │ ├── carouselContext/
│ │ │ │ │ │ │ ├── carouselProvider.tsx
│ │ │ │ │ │ │ ├── context.ts
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ │ ├── useCarousel.ts
│ │ │ │ │ │ │ ├── useCarouselKeys.ts
│ │ │ │ │ │ │ ├── useCarouselScroll.ts
│ │ │ │ │ │ │ └── useCarouselSizing.ts
│ │ │ │ │ │ ├── carouselDrawer.js
│ │ │ │ │ │ ├── carouselDrawerIcon.js
│ │ │ │ │ │ ├── carouselLayout.js
│ │ │ │ │ │ ├── carouselList.js
│ │ │ │ │ │ ├── carouselPage.js
│ │ │ │ │ │ ├── carouselScroll.js
│ │ │ │ │ │ ├── constants.ts
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ ├── carouselDrawer.karma.js
│ │ │ │ │ │ │ └── carouselNavigation.karma.js
│ │ │ │ │ │ └── skeletonPage.tsx
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── footer.js
│ │ │ │ │ ├── footerLayout.js
│ │ │ │ │ ├── gridview/
│ │ │ │ │ │ ├── gridView.js
│ │ │ │ │ │ ├── gridViewButton.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ └── gridView.karma.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── gridview.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── footerMenu.karma.js
│ │ │ │ │ │ ├── popups.karma.js
│ │ │ │ │ │ └── zoomSelector.karma.js
│ │ │ │ │ ├── layers/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── layers.js
│ │ │ │ │ ├── pagepreview/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── primaryMenu.js
│ │ │ │ │ ├── secondaryMenu.js
│ │ │ │ │ ├── toolbarToggle.js
│ │ │ │ │ ├── useFooterHeight.js
│ │ │ │ │ └── zoomSelector/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── zoomSelector.js
│ │ │ │ ├── form/
│ │ │ │ │ ├── color/
│ │ │ │ │ │ ├── activeOpacity.js
│ │ │ │ │ │ ├── applyOpacityChange.js
│ │ │ │ │ │ ├── color.js
│ │ │ │ │ │ ├── colorInput.js
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── getPreviewOpacity.js
│ │ │ │ │ │ ├── getPreviewStyle.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── opacityInput.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ ├── applyOpacityChange.js
│ │ │ │ │ │ ├── color.js
│ │ │ │ │ │ ├── colorInput.js
│ │ │ │ │ │ ├── getPreviewOpacity.js
│ │ │ │ │ │ ├── getPreviewStyle.js
│ │ │ │ │ │ └── opacityInput.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── dateTime/
│ │ │ │ │ │ ├── calendarWrapper.js
│ │ │ │ │ │ ├── datePicker.js
│ │ │ │ │ │ ├── dateTime.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── timePicker.js
│ │ │ │ │ │ ├── timeZone.js
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ ├── filterToggle/
│ │ │ │ │ │ ├── filterToggle.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── hierarchical/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── hierarchical.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── hierarchical.js
│ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ └── utils/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── link.js
│ │ │ │ │ ├── linkIcon.js
│ │ │ │ │ ├── media.js
│ │ │ │ │ ├── mediaUploadButton.js
│ │ │ │ │ ├── radioGroup/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── required.js
│ │ │ │ │ ├── row.js
│ │ │ │ │ ├── select/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── select.js
│ │ │ │ │ ├── shared/
│ │ │ │ │ │ └── useRadioNavigation.js
│ │ │ │ │ ├── stackable/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stackableGroup.js
│ │ │ │ │ │ └── stackableInput.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── link.js
│ │ │ │ │ │ ├── radioGroup.js
│ │ │ │ │ │ ├── switch.js
│ │ │ │ │ │ └── tags.js
│ │ │ │ │ ├── switch.js
│ │ │ │ │ ├── tags/
│ │ │ │ │ │ ├── description.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── input.js
│ │ │ │ │ │ ├── label.js
│ │ │ │ │ │ ├── reducer.js
│ │ │ │ │ │ ├── tag.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ ├── input.js
│ │ │ │ │ │ └── reducer.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── radioGroup.js
│ │ │ │ │ │ └── switch.js
│ │ │ │ │ ├── textArea.js
│ │ │ │ │ ├── useFormContext.js
│ │ │ │ │ ├── useHotlink.js
│ │ │ │ │ └── usePresubmitHandler.js
│ │ │ │ ├── header/
│ │ │ │ │ ├── buttons/
│ │ │ │ │ │ ├── buttonWithChecklistWarning.js
│ │ │ │ │ │ ├── historyButtons.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── preview.js
│ │ │ │ │ │ ├── publish.js
│ │ │ │ │ │ ├── switchToDraft.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── preview.js
│ │ │ │ │ │ │ ├── publish.js
│ │ │ │ │ │ │ ├── switchToDraft.js
│ │ │ │ │ │ │ └── update.js
│ │ │ │ │ │ └── update.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── previewErrorDialog.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── previewErrorDialog.js
│ │ │ │ │ └── title.js
│ │ │ │ ├── helpCenter/
│ │ │ │ │ ├── companion/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── helpCenter.karma.js
│ │ │ │ │ ├── menu/
│ │ │ │ │ │ ├── header.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── tips.js
│ │ │ │ │ │ └── transitioner.js
│ │ │ │ │ ├── navigator/
│ │ │ │ │ │ ├── bottomNavigation.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ ├── quickTip/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── transitioner.js
│ │ │ │ │ ├── toggle/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── hideOnError.tsx
│ │ │ │ ├── hotlinkModal/
│ │ │ │ │ ├── hotlinkModal.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── hotlinkDialog.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── isValidUrlForHotlinking.js
│ │ │ │ │ ├── useHotlinkModal.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── keyboardShortcutsMenu/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── headerShortcut.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── keyboardShortcuts.karma.js
│ │ │ │ │ ├── keyboardShortcutList.js
│ │ │ │ │ ├── keyboardShortcutsMenuContext/
│ │ │ │ │ │ ├── context.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── provider.tsx
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ └── useKeyboardShortcutsMenu.ts
│ │ │ │ │ ├── landmarkShortcuts.js
│ │ │ │ │ ├── regularShortcuts.js
│ │ │ │ │ ├── shortcutLabel.js
│ │ │ │ │ ├── shortcutMenu.js
│ │ │ │ │ ├── shortcutMenuSection.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── layout/
│ │ │ │ │ └── index.js
│ │ │ │ ├── library/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── searchInput.js
│ │ │ │ │ │ ├── section.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── searchInput.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ ├── libraryTabs.karma.js
│ │ │ │ │ │ ├── mediaTab.karma.js
│ │ │ │ │ │ └── shapes/
│ │ │ │ │ │ └── shapes.karma.js
│ │ │ │ │ ├── library.js
│ │ │ │ │ ├── libraryLayout.js
│ │ │ │ │ ├── libraryPanes.js
│ │ │ │ │ ├── libraryProvider.js
│ │ │ │ │ ├── libraryUploadDropTarget.js
│ │ │ │ │ ├── paneIds.ts
│ │ │ │ │ ├── panes/
│ │ │ │ │ │ ├── common/
│ │ │ │ │ │ │ └── styles.js
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ ├── common/
│ │ │ │ │ │ │ │ ├── attribution.js
│ │ │ │ │ │ │ │ ├── innerElement.js
│ │ │ │ │ │ │ │ ├── insertionMenu.js
│ │ │ │ │ │ │ │ ├── mediaElement.js
│ │ │ │ │ │ │ │ ├── mediaGallery.js
│ │ │ │ │ │ │ │ ├── paginatedMediaGallery.js
│ │ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ │ ├── mediaElement.js
│ │ │ │ │ │ │ │ │ └── mediaGallery.js
│ │ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ │ ├── accessibility.js
│ │ │ │ │ │ │ │ └── paginatedMediaGallery.js
│ │ │ │ │ │ │ ├── local/
│ │ │ │ │ │ │ │ ├── deleteDialog.js
│ │ │ │ │ │ │ │ ├── dropDownMenu.js
│ │ │ │ │ │ │ │ ├── hotlink/
│ │ │ │ │ │ │ │ │ ├── hotlink.js
│ │ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ │ └── useInsert.js
│ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ │ ├── hotlink.karma.js
│ │ │ │ │ │ │ │ │ └── mediaFetching.karma.js
│ │ │ │ │ │ │ │ ├── mediaEditDialog.js
│ │ │ │ │ │ │ │ ├── mediaIcon.js
│ │ │ │ │ │ │ │ ├── mediaPane.js
│ │ │ │ │ │ │ │ ├── mediaRecording/
│ │ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ │ └── mediaRecording.js
│ │ │ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ │ ├── deleteDialog.js
│ │ │ │ │ │ │ │ │ ├── mediaEditDialog.js
│ │ │ │ │ │ │ │ │ └── videoOptimizationDialog.js
│ │ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ │ └── videoOptimizationDialog.js
│ │ │ │ │ │ │ │ ├── useOnMediaSelect.js
│ │ │ │ │ │ │ │ └── videoOptimizationDialog.js
│ │ │ │ │ │ │ └── media3p/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── mediaFetching.karma.js
│ │ │ │ │ │ │ ├── media3pIcon.js
│ │ │ │ │ │ │ ├── media3pPane.js
│ │ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ │ ├── providerPanel.js
│ │ │ │ │ │ │ ├── providerTab.js
│ │ │ │ │ │ │ ├── providerTabList.js
│ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ └── termsDialog.js
│ │ │ │ │ │ │ ├── termsDialog.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ ├── accessibility.js
│ │ │ │ │ │ │ └── media3pPane.js
│ │ │ │ │ │ ├── pageTemplates/
│ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ ├── defaultPageTemplate.js
│ │ │ │ │ │ │ ├── defaultTemplates.js
│ │ │ │ │ │ │ ├── deleteDialog.js
│ │ │ │ │ │ │ ├── dropDownMenu.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ ├── defaultPageTemplates.karma.js
│ │ │ │ │ │ │ │ └── savedPageTemplates.karma.js
│ │ │ │ │ │ │ ├── nameDialog.js
│ │ │ │ │ │ │ ├── pageTemplatesIcon.js
│ │ │ │ │ │ │ ├── pageTemplatesPane.js
│ │ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ │ ├── savedPageTemplate.js
│ │ │ │ │ │ │ ├── savedTemplates.js
│ │ │ │ │ │ │ ├── templateList.js
│ │ │ │ │ │ │ └── templateSave.js
│ │ │ │ │ │ ├── shapes/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ │ ├── shapePreview.js
│ │ │ │ │ │ │ ├── shapesIcon.js
│ │ │ │ │ │ │ ├── shapesPane.js
│ │ │ │ │ │ │ └── stickerPreview.js
│ │ │ │ │ │ ├── shared/
│ │ │ │ │ │ │ ├── chipGroup/
│ │ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ └── stories/
│ │ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ │ ├── hooks/
│ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ ├── useExpandAnimation.js
│ │ │ │ │ │ │ │ └── useHandleRowVisibility.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── insertionOverlay.js
│ │ │ │ │ │ │ ├── libraryMoveable.js
│ │ │ │ │ │ │ └── virtualizedPanelGrid/
│ │ │ │ │ │ │ ├── components.js
│ │ │ │ │ │ │ ├── getVirtualizedItemIndex.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── getVirtualizedItemIndex.js
│ │ │ │ │ │ │ │ └── useVirtualizedGridNavigation.js
│ │ │ │ │ │ │ └── useVirtualizedGridNavigation.js
│ │ │ │ │ │ ├── shopping/
│ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── shopping.karma.js
│ │ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ │ ├── product.js
│ │ │ │ │ │ │ ├── productButton.js
│ │ │ │ │ │ │ ├── productDropdown.js
│ │ │ │ │ │ │ ├── productImage.js
│ │ │ │ │ │ │ ├── productList.js
│ │ │ │ │ │ │ ├── productPrice.js
│ │ │ │ │ │ │ ├── productSort.js
│ │ │ │ │ │ │ ├── shoppingIcon.js
│ │ │ │ │ │ │ ├── shoppingPane.js
│ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ │ └── useProductNavigation.js
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ ├── fontPreview.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ ├── savedStyles.karma.js
│ │ │ │ │ │ │ ├── textPane.karma.js
│ │ │ │ │ │ │ └── textSets.cuj.karma.js
│ │ │ │ │ │ ├── paneId.js
│ │ │ │ │ │ ├── stylePresets/
│ │ │ │ │ │ │ └── stylePresets.js
│ │ │ │ │ │ ├── textIcon.js
│ │ │ │ │ │ ├── textPane.js
│ │ │ │ │ │ ├── textPresets.ts
│ │ │ │ │ │ ├── textSets/
│ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ └── textSet.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── textSet.js
│ │ │ │ │ │ │ │ └── textSetsPane.js
│ │ │ │ │ │ │ ├── textSet.js
│ │ │ │ │ │ │ ├── textSetElements.js
│ │ │ │ │ │ │ ├── textSets.js
│ │ │ │ │ │ │ └── textSetsPane.js
│ │ │ │ │ │ └── useInsertPreset.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── _utils/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── deleteDialog.js
│ │ │ │ │ │ ├── mediaEditDialog.js
│ │ │ │ │ │ ├── mediaElement.js
│ │ │ │ │ │ ├── shapes/
│ │ │ │ │ │ │ ├── shapePreview.js
│ │ │ │ │ │ │ └── stickerPreview.js
│ │ │ │ │ │ ├── termsDialog.js
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ └── textPane.js
│ │ │ │ │ └── useLibrary.js
│ │ │ │ ├── localAutoSaveHandler/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── localAutoSave.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── localAutoSaveHandler.js
│ │ │ │ ├── mediaRecording/
│ │ │ │ │ ├── audio.js
│ │ │ │ │ ├── blur.js
│ │ │ │ │ ├── components.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── countdown.js
│ │ │ │ │ ├── durationIndicator.js
│ │ │ │ │ ├── errorDialog.js
│ │ │ │ │ ├── footer.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── mediaRecording.karma.js
│ │ │ │ │ ├── mediaRecording.js
│ │ │ │ │ ├── permissionsDialog.js
│ │ │ │ │ ├── playPauseButton.js
│ │ │ │ │ ├── playbackMedia.js
│ │ │ │ │ ├── processingOverlay.js
│ │ │ │ │ ├── progressBar.js
│ │ │ │ │ ├── provider.js
│ │ │ │ │ ├── settingsModal.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── countdown.js
│ │ │ │ │ │ ├── durationIndicator.js
│ │ │ │ │ │ ├── errorDialog.js
│ │ │ │ │ │ ├── permissionsDialog.js
│ │ │ │ │ │ ├── settingsModal.js
│ │ │ │ │ │ └── videoMode.js
│ │ │ │ │ ├── useMediaRecording.js
│ │ │ │ │ ├── useTrim.js
│ │ │ │ │ └── videoMode.js
│ │ │ │ ├── panels/
│ │ │ │ │ ├── design/
│ │ │ │ │ │ ├── alignment/
│ │ │ │ │ │ │ ├── alignment.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── alignment.karma.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── alignment.js
│ │ │ │ │ │ │ │ └── useAlignment.js
│ │ │ │ │ │ │ └── useAlignment.js
│ │ │ │ │ │ ├── animation/
│ │ │ │ │ │ │ ├── animation.js
│ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ ├── directionRadioInput.js
│ │ │ │ │ │ │ ├── effectChooserDropdown/
│ │ │ │ │ │ │ │ ├── dropdownConstants.js
│ │ │ │ │ │ │ │ ├── dropdownItem.js
│ │ │ │ │ │ │ │ ├── effectChooserDropdown.js
│ │ │ │ │ │ │ │ ├── effectChooserElements.js
│ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ │ │ ├── types.js
│ │ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ │ ├── generateDynamicProps.js
│ │ │ │ │ │ │ │ ├── getDisabledBackgroundEffects.js
│ │ │ │ │ │ │ │ ├── hasDynamicProperty.js
│ │ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ │ └── updateDynamicProps.js
│ │ │ │ │ │ │ ├── effectInput.js
│ │ │ │ │ │ │ ├── effectPanel.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── animation.karma.js
│ │ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ │ ├── directionRadioInput.js
│ │ │ │ │ │ │ │ └── effectChooser.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ ├── directionRadioInput.js
│ │ │ │ │ │ │ └── effectInput.js
│ │ │ │ │ │ ├── audioSticker/
│ │ │ │ │ │ │ ├── audioStickerStyle.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── stickerSize.js
│ │ │ │ │ │ │ ├── stickerStyle.js
│ │ │ │ │ │ │ ├── stickerType.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── stickerSize.js
│ │ │ │ │ │ │ │ ├── stickerStyle.js
│ │ │ │ │ │ │ │ └── stickerType.js
│ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ ├── border/
│ │ │ │ │ │ │ ├── border.js
│ │ │ │ │ │ │ ├── borderWidth.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── border.karma.js
│ │ │ │ │ │ │ └── shared.js
│ │ │ │ │ │ ├── captions/
│ │ │ │ │ │ │ ├── captions.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── captions.js
│ │ │ │ │ │ ├── filter/
│ │ │ │ │ │ │ ├── convertOverlay.js
│ │ │ │ │ │ │ ├── filter.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── filter.karma.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── convertOverlay.js
│ │ │ │ │ │ ├── imageAccessibility/
│ │ │ │ │ │ │ ├── imageAccessibility.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── imageAccessibility.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── link/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── link.karma.js
│ │ │ │ │ │ │ ├── link.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── link.js
│ │ │ │ │ │ ├── pageAdvancement/
│ │ │ │ │ │ │ ├── customPageAdvancement.js
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── pageAttachment/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── outlink.js
│ │ │ │ │ │ │ ├── pageAttachment.js
│ │ │ │ │ │ │ ├── shared.js
│ │ │ │ │ │ │ └── shoppingAttachment.js
│ │ │ │ │ │ ├── pageBackground/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── pageBackground.karma.js
│ │ │ │ │ │ │ ├── pageBackground.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── pageBackground.js
│ │ │ │ │ │ ├── pageBackgroundAudio/
│ │ │ │ │ │ │ ├── backgroundAudio.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── pageBackgroundAudio.karma.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── backgroundAudio.js
│ │ │ │ │ │ ├── product/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── product.js
│ │ │ │ │ │ ├── shapeStyle/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── shapeStyle.js
│ │ │ │ │ │ ├── sizePosition/
│ │ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ ├── borderRadius.karma.js
│ │ │ │ │ │ │ │ └── sizePosition.karma.js
│ │ │ │ │ │ │ ├── opacity.js
│ │ │ │ │ │ │ ├── radius.js
│ │ │ │ │ │ │ ├── sizePosition.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── sizePosition.js
│ │ │ │ │ │ │ ├── usePresubmitHandlers.js
│ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ ├── textAccessibility/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── textAccessibility.js
│ │ │ │ │ │ │ └── textAccessibility.js
│ │ │ │ │ │ ├── textStyle/
│ │ │ │ │ │ │ ├── backgroundColor.js
│ │ │ │ │ │ │ ├── color.js
│ │ │ │ │ │ │ ├── font.js
│ │ │ │ │ │ │ ├── getClosestFontWeight.js
│ │ │ │ │ │ │ ├── getFontWeights.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ ├── contrast.karma.js
│ │ │ │ │ │ │ │ ├── stylePresets.karma.js
│ │ │ │ │ │ │ │ └── textStyle.other.karma.js
│ │ │ │ │ │ │ ├── padding.js
│ │ │ │ │ │ │ ├── panelHeader.js
│ │ │ │ │ │ │ ├── style.js
│ │ │ │ │ │ │ ├── stylePresets.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ ├── fontPicker.js
│ │ │ │ │ │ │ │ ├── fontsResponse.json
│ │ │ │ │ │ │ │ ├── getClosestFontWeight.js
│ │ │ │ │ │ │ │ ├── getFontWeights.js
│ │ │ │ │ │ │ │ ├── stylePresetPanel.js
│ │ │ │ │ │ │ │ ├── textBox.js
│ │ │ │ │ │ │ │ └── textStyle.js
│ │ │ │ │ │ │ ├── textStyle.js
│ │ │ │ │ │ │ ├── useRichTextFormatting.js
│ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ ├── videoAccessibility/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── videoPoster.karma.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── videoAccessibility.js
│ │ │ │ │ │ │ └── videoAccessibility.js
│ │ │ │ │ │ ├── videoOptions/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ │ └── videoOptions.karma.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── videoOptions.js
│ │ │ │ │ │ │ └── videoOptions.js
│ │ │ │ │ │ ├── videoSegment/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── videoSegment.js
│ │ │ │ │ │ └── warning/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── warning.js
│ │ │ │ │ ├── document/
│ │ │ │ │ │ ├── backgroundAudio/
│ │ │ │ │ │ │ ├── backgroundAudio.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── backgroundAudio.js
│ │ │ │ │ │ ├── excerpt/
│ │ │ │ │ │ │ ├── excerpt.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── excerpt.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── pageAdvancement/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── pageAdvancement.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── pageAdvancement.js
│ │ │ │ │ │ ├── slug/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── slug.js
│ │ │ │ │ │ │ └── test/
│ │ │ │ │ │ │ └── slug.js
│ │ │ │ │ │ └── taxonomies/
│ │ │ │ │ │ ├── FlatTermSelector.js
│ │ │ │ │ │ ├── HierarchicalTermSelector.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ └── taxonomies.karma.js
│ │ │ │ │ │ ├── shared.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── taxonomies.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── taxonomies.js
│ │ │ │ │ ├── layer/
│ │ │ │ │ │ ├── constants.js
│ │ │ │ │ │ ├── elementLayer.js
│ │ │ │ │ │ ├── elementLayerActions.js
│ │ │ │ │ │ ├── groupLayer.js
│ │ │ │ │ │ ├── groupLayerActions.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── karma/
│ │ │ │ │ │ │ └── layer.karma.js
│ │ │ │ │ │ ├── layer.js
│ │ │ │ │ │ ├── layerAction.js
│ │ │ │ │ │ ├── layerComponents.js
│ │ │ │ │ │ ├── layerForm.js
│ │ │ │ │ │ ├── layerIdContext.js
│ │ │ │ │ │ ├── layerList.js
│ │ │ │ │ │ ├── layerPanel.js
│ │ │ │ │ │ ├── reorderableElementLayer.js
│ │ │ │ │ │ ├── reorderableGroupLayer.js
│ │ │ │ │ │ ├── reorderableLayer.js
│ │ │ │ │ │ ├── shapeMaskWrapper.js
│ │ │ │ │ │ ├── useGroupSelection.js
│ │ │ │ │ │ ├── useLayerSelection.js
│ │ │ │ │ │ └── useLayers.js
│ │ │ │ │ ├── panel/
│ │ │ │ │ │ ├── context.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── panel.js
│ │ │ │ │ │ ├── shared/
│ │ │ │ │ │ │ ├── content.js
│ │ │ │ │ │ │ ├── handle.js
│ │ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ │ └── handle.js
│ │ │ │ │ │ │ └── title.js
│ │ │ │ │ │ ├── simplePanel.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ └── simplePanel.js
│ │ │ │ │ │ ├── useDragHandlers.js
│ │ │ │ │ │ └── useKeyboardHandlers.js
│ │ │ │ │ ├── shared/
│ │ │ │ │ │ ├── flipControls.js
│ │ │ │ │ │ ├── generalPageAdvancement.js
│ │ │ │ │ │ ├── getCommonObjectValue.js
│ │ │ │ │ │ ├── getCommonValue.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── linkRelations.js
│ │ │ │ │ │ ├── media/
│ │ │ │ │ │ │ ├── audioPlayer.js
│ │ │ │ │ │ │ ├── backgroundAudioPanelContent.js
│ │ │ │ │ │ │ ├── captionsPanelContent.js
│ │ │ │ │ │ │ ├── dropDownMenu.js
│ │ │ │ │ │ │ ├── fileRow.js
│ │ │ │ │ │ │ └── loopPanelContent.js
│ │ │ │ │ │ ├── styles.js
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── _utils.js
│ │ │ │ │ │ │ ├── getCommonObjectValue.js
│ │ │ │ │ │ │ └── linkRelations.js
│ │ │ │ │ │ ├── useCommonColorValue.js
│ │ │ │ │ │ └── useCommonObjectValue.js
│ │ │ │ │ └── utils/
│ │ │ │ │ ├── dropDownKeyEvents.js
│ │ │ │ │ ├── metricsForTextPadding.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── metricsForTextPadding.js
│ │ │ │ ├── previewPage/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── previewErrorBoundary.js
│ │ │ │ │ ├── previewPage.js
│ │ │ │ │ └── previewPageElements.js
│ │ │ │ ├── publishModal/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── content/
│ │ │ │ │ │ ├── checklistButton.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── mainStoryInfo.js
│ │ │ │ │ │ └── storyPreview.js
│ │ │ │ │ ├── header/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── publishModal.karma.js
│ │ │ │ │ ├── publishModal.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ ├── content.js
│ │ │ │ │ ├── header.js
│ │ │ │ │ ├── mainStoryInfo.js
│ │ │ │ │ └── storyPreview.js
│ │ │ │ ├── reorderable/
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── reorderable.js
│ │ │ │ │ ├── reorderableItem.js
│ │ │ │ │ ├── reorderableScroller.js
│ │ │ │ │ ├── reorderableSeparator.js
│ │ │ │ │ ├── useReorderable.js
│ │ │ │ │ ├── useReordering.js
│ │ │ │ │ └── useScroll.js
│ │ │ │ ├── secondaryPopup/
│ │ │ │ │ ├── components.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── navigationWrapper.js
│ │ │ │ │ ├── topNavigation.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── shopping/
│ │ │ │ │ └── frame.js
│ │ │ │ ├── sidebar/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── karma/
│ │ │ │ │ │ └── sidebarTabs.karma.js
│ │ │ │ │ ├── sidebar.js
│ │ │ │ │ ├── sidebarContent.js
│ │ │ │ │ ├── sidebarLayout.js
│ │ │ │ │ ├── sidebarProvider.js
│ │ │ │ │ ├── useSidebar.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── storyFontPicker/
│ │ │ │ │ └── index.js
│ │ │ │ ├── style/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── designPanel.js
│ │ │ │ │ ├── getDesignPanelsForSelection.js
│ │ │ │ │ ├── icons/
│ │ │ │ │ │ ├── animationIcon.js
│ │ │ │ │ │ ├── audioStickerSelectionIcon.js
│ │ │ │ │ │ ├── imageSelectionIcon.js
│ │ │ │ │ │ ├── linkIcon.js
│ │ │ │ │ │ ├── multiSelectionIcon.js
│ │ │ │ │ │ ├── productSelectionIcon.js
│ │ │ │ │ │ ├── selectionIcon.js
│ │ │ │ │ │ ├── shapeSelectionIcon.js
│ │ │ │ │ │ ├── textSelectionIcon.js
│ │ │ │ │ │ └── videoSelectionIcon.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── style.js
│ │ │ │ │ ├── styleLayout.js
│ │ │ │ │ ├── stylePanes.js
│ │ │ │ │ ├── styleProvider.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── designPanel.js
│ │ │ │ │ │ └── updateProperties.js
│ │ │ │ │ ├── updateProperties.js
│ │ │ │ │ ├── useDesignPanels.js
│ │ │ │ │ └── useStyle.js
│ │ │ │ ├── styleManager/
│ │ │ │ │ ├── components.js
│ │ │ │ │ ├── confirmationDialog.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── header.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── confirmationDialog.js
│ │ │ │ │ ├── styleGroup.js
│ │ │ │ │ ├── styleItem.js
│ │ │ │ │ ├── styleManager.js
│ │ │ │ │ ├── useApplyStyle.js
│ │ │ │ │ ├── useDeleteStyle.js
│ │ │ │ │ └── useKeyboardNavigation.js
│ │ │ │ ├── tablist/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styles.js
│ │ │ │ │ └── tablistPanel.js
│ │ │ │ ├── tabview/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── thumbnail/
│ │ │ │ │ ├── components/
│ │ │ │ │ │ └── LayerThumbnail.js
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── overflowThumbnail.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ ├── demoThumbnails.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── styles.js
│ │ │ │ │ └── thumbnail.js
│ │ │ │ ├── toggleButton/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── stories/
│ │ │ │ │ └── index.js
│ │ │ │ ├── tooltip/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── tooltip.js
│ │ │ │ ├── transition/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── scheduledTransition.js
│ │ │ │ ├── uploadDropTarget/
│ │ │ │ │ ├── context.js
│ │ │ │ │ ├── dropTarget.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── message.js
│ │ │ │ │ ├── overlay.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── dropTarget.js
│ │ │ │ │ └── use.js
│ │ │ │ ├── videoTrim/
│ │ │ │ │ ├── constants.js
│ │ │ │ │ ├── currentTime.js
│ │ │ │ │ ├── generateVideoStrip.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── provider.js
│ │ │ │ │ ├── recordingProvider.js
│ │ │ │ │ ├── slider.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── useVideoNode.js
│ │ │ │ │ │ ├── useVideoTrimMode.js
│ │ │ │ │ │ └── videoTrimmer.js
│ │ │ │ │ ├── trimmerComponents.js
│ │ │ │ │ ├── useRailBackground.js
│ │ │ │ │ ├── useVideoNode.js
│ │ │ │ │ ├── useVideoTrim.js
│ │ │ │ │ ├── useVideoTrimMode.js
│ │ │ │ │ ├── videoTrimContext.js
│ │ │ │ │ └── videoTrimmer.js
│ │ │ │ └── workspace/
│ │ │ │ ├── index.js
│ │ │ │ └── layout.js
│ │ │ ├── constants/
│ │ │ │ ├── audioSticker.ts
│ │ │ │ ├── fonts.ts
│ │ │ │ ├── headings.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── media.ts
│ │ │ │ ├── multipleValue.ts
│ │ │ │ ├── performanceTrackingEvents.ts
│ │ │ │ └── zIndex.ts
│ │ │ ├── dataUtils/
│ │ │ │ └── formattedTemplatesArray.js
│ │ │ ├── getDefaultConfig.js
│ │ │ ├── icons/
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ ├── karma/
│ │ │ │ ├── copyAndPaste.cuj.karma.js
│ │ │ │ ├── duplicate.cuj.karma.js
│ │ │ │ ├── element-library/
│ │ │ │ │ ├── audio-sticker/
│ │ │ │ │ │ └── audioSticker.karma.js
│ │ │ │ │ ├── image/
│ │ │ │ │ │ ├── edit.karma.js
│ │ │ │ │ │ └── resourceLoading.karma.js
│ │ │ │ │ ├── text/
│ │ │ │ │ │ ├── edit.karma.js
│ │ │ │ │ │ └── frame.karma.js
│ │ │ │ │ └── video/
│ │ │ │ │ ├── autoplay.karma.js
│ │ │ │ │ └── elementMinSizeAndPlayback.karma.js
│ │ │ │ ├── elementTransform.cuj.karma.js
│ │ │ │ ├── fixture/
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── checklist/
│ │ │ │ │ │ │ ├── accessibility/
│ │ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ │ ├── design/
│ │ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── priority/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ ├── documentPane/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── header/
│ │ │ │ │ │ ├── buttons/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── containers/
│ │ │ │ │ │ ├── canvas.js
│ │ │ │ │ │ ├── carousel.js
│ │ │ │ │ │ ├── checklist.js
│ │ │ │ │ │ ├── common/
│ │ │ │ │ │ │ ├── color.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── radio.js
│ │ │ │ │ │ │ ├── select.js
│ │ │ │ │ │ │ ├── toggle.js
│ │ │ │ │ │ │ └── toggleButton.js
│ │ │ │ │ │ ├── container.js
│ │ │ │ │ │ ├── designMenu.js
│ │ │ │ │ │ ├── designPanel/
│ │ │ │ │ │ │ ├── abstractPanel.js
│ │ │ │ │ │ │ ├── alignment.js
│ │ │ │ │ │ │ ├── animationPanel.js
│ │ │ │ │ │ │ ├── audioStickerSize.js
│ │ │ │ │ │ │ ├── audioStickerStyle.js
│ │ │ │ │ │ │ ├── audioStickerType.js
│ │ │ │ │ │ │ ├── border.js
│ │ │ │ │ │ │ ├── captions.js
│ │ │ │ │ │ │ ├── colorPreset.js
│ │ │ │ │ │ │ ├── filter.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── layers.js
│ │ │ │ │ │ │ ├── link.js
│ │ │ │ │ │ │ ├── pageBackground.js
│ │ │ │ │ │ │ ├── pageBackgroundAudio.js
│ │ │ │ │ │ │ ├── shapeStyle.js
│ │ │ │ │ │ │ ├── sizePosition.js
│ │ │ │ │ │ │ ├── textStyle.js
│ │ │ │ │ │ │ ├── videoOptions.js
│ │ │ │ │ │ │ └── videoPoster.js
│ │ │ │ │ │ ├── documentPanel/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── taxonomies.js
│ │ │ │ │ │ ├── editor.js
│ │ │ │ │ │ ├── footer.js
│ │ │ │ │ │ ├── gridView.js
│ │ │ │ │ │ ├── header.js
│ │ │ │ │ │ ├── helpCenter.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── keyboardShortcuts.js
│ │ │ │ │ │ ├── library/
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── pageTemplates.js
│ │ │ │ │ │ │ └── text.js
│ │ │ │ │ │ ├── quickActionMenu.js
│ │ │ │ │ │ └── sidebar.js
│ │ │ │ │ ├── db/
│ │ │ │ │ │ ├── getMediaResponse.js
│ │ │ │ │ │ ├── getProductsResponse.js
│ │ │ │ │ │ ├── getTaxonomiesResponse.js
│ │ │ │ │ │ ├── getTaxonomyTermResponse.js
│ │ │ │ │ │ ├── singleSavedTemplate.js
│ │ │ │ │ │ └── storyResponse.js
│ │ │ │ │ ├── fixture.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ ├── integrationLayerTesting/
│ │ │ │ │ ├── config.karma.js
│ │ │ │ │ └── optionalCallbacks.karma.js
│ │ │ │ ├── media.cuj.karma.js
│ │ │ │ ├── richText/
│ │ │ │ │ ├── _utils.js
│ │ │ │ │ ├── inlineSelection.karma.js
│ │ │ │ │ ├── inlineStyleOverride.karma.js
│ │ │ │ │ ├── multiSelection.karma.js
│ │ │ │ │ └── singleSelection.karma.js
│ │ │ │ └── text.cuj.karma.js
│ │ │ ├── propTypes.js
│ │ │ ├── storyEditor.js
│ │ │ ├── theme.js
│ │ │ ├── types/
│ │ │ │ ├── apiProvider.ts
│ │ │ │ ├── canvasProvider.ts
│ │ │ │ ├── configProvider.ts
│ │ │ │ ├── currentUserProvider.ts
│ │ │ │ ├── highlightsProvider.ts
│ │ │ │ ├── historyProvider.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── layoutProvider.ts
│ │ │ │ ├── pageCanvas.ts
│ │ │ │ ├── pageDataUrls.ts
│ │ │ │ ├── story.ts
│ │ │ │ ├── storyEditor.ts
│ │ │ │ ├── storyProvider.ts
│ │ │ │ ├── storyTriggers.ts
│ │ │ │ └── taxonomyProvider.ts
│ │ │ ├── typings/
│ │ │ │ ├── apcx-hues.d.ts
│ │ │ │ ├── colorthief.d.ts
│ │ │ │ ├── dom.d.ts
│ │ │ │ ├── global.d.ts
│ │ │ │ ├── libheif-js.d.ts
│ │ │ │ └── svg.d.ts
│ │ │ └── utils/
│ │ │ ├── __mocks__/
│ │ │ │ └── getBlurHashFromImage.js
│ │ │ ├── cleanForSlug.ts
│ │ │ ├── contrastUtils.ts
│ │ │ ├── copyPaste.tsx
│ │ │ ├── createError.ts
│ │ │ ├── createThumbnailCanvasFromFullbleedCanvas.ts
│ │ │ ├── dragEvent.ts
│ │ │ ├── generateBlurhash.worker.js
│ │ │ ├── generateGroupName.ts
│ │ │ ├── getBlurHashFromImage.js
│ │ │ ├── getCropParams.ts
│ │ │ ├── getInUseFonts.ts
│ │ │ ├── getInsertedElementSize.ts
│ │ │ ├── getMediaBaseColor.ts
│ │ │ ├── getSessionStorageKey.ts
│ │ │ ├── getUniquePresets.ts
│ │ │ ├── getUpdatedSizeAndPosition.js
│ │ │ ├── idleCallback.ts
│ │ │ ├── isDefaultPage.ts
│ │ │ ├── isOffCanvas.ts
│ │ │ ├── isTargetOutOfContainer.ts
│ │ │ ├── keyboardOnlyOutline.js
│ │ │ ├── nativeCopyPasteExpected.ts
│ │ │ ├── noop.ts
│ │ │ ├── objectPick.ts
│ │ │ ├── objectWithout.ts
│ │ │ ├── presetUtils.js
│ │ │ ├── removeDupsFromArray.ts
│ │ │ ├── storyUpdates.ts
│ │ │ ├── test/
│ │ │ │ ├── cleanForSlug.js
│ │ │ │ ├── contrastUtils.js
│ │ │ │ ├── copyPaste.js
│ │ │ │ ├── createError.js
│ │ │ │ ├── generateGroupName.js
│ │ │ │ ├── getCropParams.js
│ │ │ │ ├── getInUseFonts.js
│ │ │ │ ├── getInsertedElementSize.js
│ │ │ │ ├── getUniquePresets.js
│ │ │ │ ├── isDefaultPage.js
│ │ │ │ ├── isOffCanvas.js
│ │ │ │ ├── nativeCopyPasteExpected.js
│ │ │ │ ├── objectPick.js
│ │ │ │ ├── presetUtils.js
│ │ │ │ ├── removeDupsFromArray.js
│ │ │ │ ├── storyUpdates.js
│ │ │ │ ├── textMeasurements.js
│ │ │ │ ├── useElementsWithLinks.js
│ │ │ │ ├── useGlobalClipboardHandlers.js
│ │ │ │ ├── useHandlers.js
│ │ │ │ ├── useIdleTaskQueue.js
│ │ │ │ ├── useIsUploadingToStory.js
│ │ │ │ ├── usePreventWindowUnload.js
│ │ │ │ └── useRovingTabIndex.js
│ │ │ ├── useAddPreset.js
│ │ │ ├── useApplyTextAutoStyle.js
│ │ │ ├── useCORSProxy.ts
│ │ │ ├── useDoubleClick.ts
│ │ │ ├── useElementPolygon.js
│ │ │ ├── useElementsWithLinks.ts
│ │ │ ├── useFocusTrapping.js
│ │ │ ├── useGlobalClipboardHandlers.ts
│ │ │ ├── useHandlers.ts
│ │ │ ├── useIdleTaskQueue.ts
│ │ │ ├── useIsUploadingToStory.js
│ │ │ ├── usePerformanceTracking.ts
│ │ │ ├── usePreventWindowUnload.ts
│ │ │ ├── useRefreshPostEditURL.ts
│ │ │ ├── useRovingTabIndex/
│ │ │ │ ├── flatNavigation.js
│ │ │ │ ├── index.js
│ │ │ │ └── nestedNavigation.js
│ │ │ ├── useShapeMask.js
│ │ │ └── useShapeMaskElements.js
│ │ └── tsconfig.json
│ ├── templates/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── cli.js
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── getMetaData.ts
│ │ │ ├── getTemplates.ts
│ │ │ ├── index.ts
│ │ │ ├── raw/
│ │ │ │ ├── 12-hours-in-barcelona/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── a-day-in-the-life/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── ace-hotel-kyoto-review/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── album-releases/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── all-about-cars/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── almodos-films/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── an-artists-legacy/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── art-books-gift-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── baking-bread-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── beauty-quiz/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── belly-fat-workout/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── buying-art-on-the-internet/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── celebrity-life-story/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── celebrity-q-and-a/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── diy-home-office/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── doers-get-more-done/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── elegant-travel-itinerary/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── experience-thailand/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── fashion-inspiration/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── fashion-on-the-go/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── fitness-apps-ranked/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── food-and-stuff/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── fresh-and-bright/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── google-music-studio-tour/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── hawaii-travel-packing-list/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── honeymooning-in-italy/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── house-hunting/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── how-contact-tracing-works/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── how-video-calls-saved-the-day/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── indoor-garden-oasis/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── kitchen-makeover/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── kitchen-stories/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── laptop-buying-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── los-angeles-city-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── magazine-article/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── modernist-travel-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── new-york-party-round-up/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── no-days-off/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── one-day-city-itinerary/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── pizzas-in-nyc/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── plant-based-dyes/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── pride-month-watchlist/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── rock-music-festival/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── sangria-artichoke/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── self-care-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── series-best-of/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── simple-tech-tutorial/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── skin-care-at-home/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── sleep/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── sports-quiz/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── street-style-on-the-go/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── summer-adventure-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── summer-fashion-collection/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── sustainability-tips/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── technology-advice/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── tips-for-throwing-an-outdoor-luau/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── tv-show-recap/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── ultimate-comparison/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── vintage-chairs-buying-guide/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ ├── ways-to-eat-avocado/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metaData.ts
│ │ │ │ │ ├── template.d.ts
│ │ │ │ │ └── template.json
│ │ │ │ └── weekly-entertainment/
│ │ │ │ ├── index.ts
│ │ │ │ ├── metaData.ts
│ │ │ │ ├── template.d.ts
│ │ │ │ └── template.json
│ │ │ ├── test/
│ │ │ │ ├── getTemplates.js
│ │ │ │ └── raw.js
│ │ │ ├── types.ts
│ │ │ └── utils/
│ │ │ ├── memoize.ts
│ │ │ └── test/
│ │ │ └── memoize.js
│ │ └── tsconfig.json
│ ├── test-utils/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── firePointerEvent.ts
│ │ │ ├── index.ts
│ │ │ ├── queryByAriaLabel.ts
│ │ │ ├── queryByAutoAdvanceAfter.ts
│ │ │ ├── queryById.ts
│ │ │ ├── renderWithTheme.tsx
│ │ │ └── typings/
│ │ │ └── svg.d.ts
│ │ └── tsconfig.json
│ ├── text-sets/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── cli.js
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ ├── loadTextSets.ts
│ │ │ ├── raw/
│ │ │ │ ├── contact.json
│ │ │ │ ├── cover.json
│ │ │ │ ├── editorial.json
│ │ │ │ ├── list.json
│ │ │ │ ├── quote.json
│ │ │ │ ├── section_header.json
│ │ │ │ ├── step.json
│ │ │ │ └── table.json
│ │ │ ├── test/
│ │ │ │ └── raw.js
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── tinymce-button/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── components/
│ │ │ ├── Modal.js
│ │ │ ├── controls/
│ │ │ │ ├── Toggle.js
│ │ │ │ └── test/
│ │ │ │ └── Toggle.js
│ │ │ └── test/
│ │ │ └── Modal.js
│ │ ├── containers/
│ │ │ └── Modal.js
│ │ ├── index.js
│ │ ├── store/
│ │ │ ├── actions.js
│ │ │ ├── default.js
│ │ │ ├── index.js
│ │ │ ├── reducers.js
│ │ │ ├── selectors.js
│ │ │ └── test/
│ │ │ ├── actions.js
│ │ │ └── selectors.js
│ │ └── utils/
│ │ ├── index.js
│ │ └── test/
│ │ └── index.js
│ ├── tracking/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── constants.ts
│ │ │ ├── disableTracking.ts
│ │ │ ├── enableTracking.ts
│ │ │ ├── getTimeTracker.ts
│ │ │ ├── index.ts
│ │ │ ├── initializeErrorReporting.ts
│ │ │ ├── initializeTracking.ts
│ │ │ ├── isTrackingEnabled.ts
│ │ │ ├── shared.ts
│ │ │ ├── test/
│ │ │ │ ├── disableTracking.ts
│ │ │ │ ├── enableTracking.ts
│ │ │ │ ├── getTimeTracker.ts
│ │ │ │ ├── gtag.ts
│ │ │ │ ├── initializeTracking.ts
│ │ │ │ ├── isTrackingEnabled.ts
│ │ │ │ ├── trackError.ts
│ │ │ │ ├── trackEvent.ts
│ │ │ │ ├── trackScreenView.ts
│ │ │ │ └── trackTiming.ts
│ │ │ ├── track.ts
│ │ │ ├── trackClick.ts
│ │ │ ├── trackError.ts
│ │ │ ├── trackEvent.ts
│ │ │ ├── trackScreenView.ts
│ │ │ └── trackTiming.ts
│ │ └── tsconfig.json
│ ├── transform/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── context.ts
│ │ │ ├── index.ts
│ │ │ ├── transformProvider.tsx
│ │ │ ├── types.ts
│ │ │ ├── useTransform.ts
│ │ │ └── useTransformHandler.ts
│ │ └── tsconfig.json
│ ├── units/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── calcRotatedObjectPositionAndSize.ts
│ │ │ ├── calcRotatedResizeOffset.ts
│ │ │ ├── constants.ts
│ │ │ ├── context.ts
│ │ │ ├── dimensions.ts
│ │ │ ├── getBoundRect.ts
│ │ │ ├── getCorner.ts
│ │ │ ├── getCorners.ts
│ │ │ ├── index.ts
│ │ │ ├── range.ts
│ │ │ ├── test/
│ │ │ │ ├── getBoundRect.ts
│ │ │ │ └── range.ts
│ │ │ ├── types.ts
│ │ │ ├── unitsProvider.tsx
│ │ │ └── useUnits.ts
│ │ └── tsconfig.json
│ ├── url/
│ │ ├── .npmignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── addQueryArgs.ts
│ │ │ ├── index.ts
│ │ │ ├── safeDecodeUriComponent.ts
│ │ │ ├── test/
│ │ │ │ ├── addQueryArgs.ts
│ │ │ │ ├── safeDecodeUriComponent.js
│ │ │ │ └── url.ts
│ │ │ └── url.ts
│ │ └── tsconfig.json
│ ├── widget/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── index.js
│ │ └── style.css
│ ├── wp-dashboard/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── api/
│ │ │ ├── authors.js
│ │ │ ├── constants/
│ │ │ │ └── index.js
│ │ │ ├── fonts.js
│ │ │ ├── hooks/
│ │ │ │ ├── useApiAlerts.js
│ │ │ │ ├── useFontsApi.js
│ │ │ │ ├── useMediaApi.js
│ │ │ │ ├── usePagesApi.js
│ │ │ │ ├── usePublisherLogosApi.js
│ │ │ │ ├── useSettingsApi.js
│ │ │ │ └── useUserApi.js
│ │ │ ├── index.js
│ │ │ ├── media.js
│ │ │ ├── pages.js
│ │ │ ├── publisherLogo.js
│ │ │ ├── reducers/
│ │ │ │ ├── media.js
│ │ │ │ ├── publisherLogos.js
│ │ │ │ ├── settings.js
│ │ │ │ └── test/
│ │ │ │ ├── media.js
│ │ │ │ ├── publisherLogos.js
│ │ │ │ └── settings.js
│ │ │ ├── settings.js
│ │ │ ├── shopping.js
│ │ │ ├── story.js
│ │ │ ├── taxonomies.js
│ │ │ ├── test/
│ │ │ │ ├── editorSettingsApi.js
│ │ │ │ └── user.js
│ │ │ ├── user.js
│ │ │ └── utils/
│ │ │ ├── index.js
│ │ │ ├── reshapeStoryObject.js
│ │ │ └── test/
│ │ │ └── reshapeStoryObject.js
│ │ ├── components/
│ │ │ ├── editorSettings/
│ │ │ │ ├── adManagement/
│ │ │ │ │ ├── adNetwork/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── adNetwork.js
│ │ │ │ │ ├── googleAdManager/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── googleAdManager.js
│ │ │ │ │ ├── googleAdSense/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── googleAdSense.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── mgid/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── stories/
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── test/
│ │ │ │ │ │ └── mgid.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── adManagement.js
│ │ │ │ ├── archive/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── archive.js
│ │ │ │ ├── components.js
│ │ │ │ ├── context.js
│ │ │ │ ├── customFonts/
│ │ │ │ │ ├── confirmationDialog.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── customFonts.js
│ │ │ │ │ └── utils/
│ │ │ │ │ └── getFontDataFromUrl.js
│ │ │ │ ├── dataRemoval/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── DataRemovalSettings.js
│ │ │ │ ├── dataUtils/
│ │ │ │ │ ├── formattedCustomFonts.js
│ │ │ │ │ └── formattedPublisherLogos.js
│ │ │ │ ├── editorSettings.js
│ │ │ │ ├── editorSettingsProvider.js
│ │ │ │ ├── googleAnalytics/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── googleAnalytics.js
│ │ │ │ ├── index.js
│ │ │ │ ├── mediaOptimization/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── mediaOptimizationSettings.js
│ │ │ │ ├── pageAdvancement/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── pageAdvancement.js
│ │ │ │ ├── publisherLogo/
│ │ │ │ │ ├── gridItem.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── popoverLogoContextMenu.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── publisherLogo.js
│ │ │ │ ├── shopping/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── shopify/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── shoppingProviderDropDown.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ ├── shopping.js
│ │ │ │ │ └── shoppingProvider.js
│ │ │ │ ├── telemetry/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── stories/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── telemetrySettings.js
│ │ │ │ ├── test/
│ │ │ │ │ └── editorSettings.js
│ │ │ │ ├── useEditorSettings.js
│ │ │ │ ├── utils/
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── validateAdManagerSlotIdFormat.js
│ │ │ │ │ │ ├── validateAdSensePublisherIdFormat.js
│ │ │ │ │ │ ├── validateAdSenseSlotIdFormat.js
│ │ │ │ │ │ ├── validateGoogleAnalyticsIdFormat.js
│ │ │ │ │ │ ├── validateMgidWidgetIdFormat.js
│ │ │ │ │ │ └── validateShopifyHost.js
│ │ │ │ │ ├── validateAdManagerSlotIdFormat.js
│ │ │ │ │ ├── validateAdSensePublisherIdFormat.js
│ │ │ │ │ ├── validateAdSenseSlotIdFormat.js
│ │ │ │ │ ├── validateGoogleAnalyticsIdFormat.js
│ │ │ │ │ ├── validateMgidWidgetIdFormat.js
│ │ │ │ │ └── validateShopifyHost.js
│ │ │ │ └── videoCache/
│ │ │ │ ├── index.js
│ │ │ │ ├── stories/
│ │ │ │ │ └── index.js
│ │ │ │ └── test/
│ │ │ │ └── videoCache.js
│ │ │ ├── ga4Banner/
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ ├── layout/
│ │ │ │ └── index.js
│ │ │ ├── telemetryBanner/
│ │ │ │ ├── index.js
│ │ │ │ ├── stories/
│ │ │ │ │ └── telemetryBanner.js
│ │ │ │ └── test/
│ │ │ │ └── telemetryBanner.js
│ │ │ └── updateBanner/
│ │ │ └── index.js
│ │ ├── constants/
│ │ │ ├── index.js
│ │ │ ├── settings.js
│ │ │ ├── textConstants.js
│ │ │ └── wpAdmin.js
│ │ ├── effects/
│ │ │ ├── index.js
│ │ │ ├── useMediaOptimization.js
│ │ │ ├── useSyncAdminMenu.js
│ │ │ └── useTelemetryOptIn.js
│ │ ├── index.js
│ │ ├── publicPath.js
│ │ ├── setLocaleData.js
│ │ ├── style.css
│ │ ├── testUtils/
│ │ │ ├── index.js
│ │ │ ├── mockEditorProvider.js
│ │ │ └── renderWithProviders.js
│ │ └── theme.js
│ ├── wp-story-editor/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ ├── api/
│ │ │ ├── authors.js
│ │ │ ├── constants/
│ │ │ │ └── index.js
│ │ │ ├── fonts.js
│ │ │ ├── hotlinkInfo.js
│ │ │ ├── index.js
│ │ │ ├── media.js
│ │ │ ├── metaboxes.js
│ │ │ ├── metadata.js
│ │ │ ├── pageTemplate.js
│ │ │ ├── proxy.js
│ │ │ ├── publisherLogos.js
│ │ │ ├── shopping.js
│ │ │ ├── statusCheck.js
│ │ │ ├── story.js
│ │ │ ├── storyLock.js
│ │ │ ├── taxonomy.js
│ │ │ ├── test/
│ │ │ │ ├── _utils.js
│ │ │ │ ├── fonts.js
│ │ │ │ ├── media.js
│ │ │ │ ├── metaboxes.js
│ │ │ │ ├── pageTemplates.js
│ │ │ │ ├── story.js
│ │ │ │ └── user.js
│ │ │ ├── user.js
│ │ │ └── utils/
│ │ │ ├── base64Encode.js
│ │ │ ├── flattenFormData.js
│ │ │ ├── getResourceFromAttachment.js
│ │ │ ├── index.js
│ │ │ ├── normalizeResourceSizes.js
│ │ │ ├── test/
│ │ │ │ ├── base64Encode.js
│ │ │ │ ├── flatternFormData.js
│ │ │ │ └── normalizeResourceSizes.js
│ │ │ └── transformStoryResponse.js
│ │ ├── components/
│ │ │ ├── checklist/
│ │ │ │ ├── accessibility/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── videoOptimizationCheckbox/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── index.js
│ │ │ │ ├── design/
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ └── priority/
│ │ │ │ ├── index.js
│ │ │ │ └── storyMissingPublisherName.js
│ │ │ ├── corsCheck/
│ │ │ │ ├── corsCheck.js
│ │ │ │ ├── corsCheckFailed.js
│ │ │ │ ├── index.js
│ │ │ │ ├── stories/
│ │ │ │ │ └── corsCheckFailed.js
│ │ │ │ └── test/
│ │ │ │ └── corsCheck.js
│ │ │ ├── crossOriginIsolation/
│ │ │ │ └── index.js
│ │ │ ├── documentPane/
│ │ │ │ ├── index.js
│ │ │ │ ├── publish/
│ │ │ │ │ ├── author.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── publish.js
│ │ │ │ │ ├── publishTime.js
│ │ │ │ │ └── test/
│ │ │ │ │ └── publish.js
│ │ │ │ └── status/
│ │ │ │ ├── index.js
│ │ │ │ ├── status.js
│ │ │ │ └── test/
│ │ │ │ └── status.js
│ │ │ ├── fontCheck/
│ │ │ │ ├── fontCheckDialog.js
│ │ │ │ ├── index.js
│ │ │ │ └── test/
│ │ │ │ └── fontCheck.js
│ │ │ ├── header/
│ │ │ │ ├── buttons/
│ │ │ │ │ ├── index.js
│ │ │ │
================================================
FILE CONTENTS
================================================
================================================
FILE: .allstar/branch_protection.yaml
================================================
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
dismissStale: false
================================================
FILE: .browserslistrc
================================================
last 2 Chrome versions
last 2 Firefox versions
last 2 Safari versions
last 2 iOS versions
last 2 Edge versions
last 2 Opera versions
================================================
FILE: .distignore
================================================
.allstar
.git
.github
.husky
.idea
.rollup.cache
.storybook
.wordpress-org
__mocks__
__static__
assets/testjs
bin
build
docs
includes/composer.json
karma
node_modules
packages
patches
plugin-assets
public
sitemap-generator
static
tests
third-party/composer.json
/vendor
web-stories-scraper
.browserslistrc
.DS_Store
.distignore
.editorconfig
.eslintignore
.eslintrc
.git-blame-ignore-revs
.gitattributes
.gitignore
.markdownlint.json
.markdownlintignore
.npmignore
.npmpackagejsonlintrc.json
.npmrc
.nvmrc
.oxlintrc.json
.phpstorm.config.js
.phpstorm.meta.php
.phpunit.result.cache
.prettierignore
.prettierrc
.stylelintignore
.stylelintrc
.test_artifacts
babel.config.cjs
bun.lockb
codecov.yml
composer.lock
CONTRIBUTING.md
jest-puppeteer.config.cjs
jsconfig.json
karma-story-editor.config.cjs
karma-dashboard.config.cjs
package.json
package-lock.json
percy.config.karma.yml
percy.config.yml
phpcs.xml
phpcs.xml.dist
phpmd.xml
phpstan.neon
phpstan.neon.dist
phpunit.xml
phpunit.xml.dist
phpunit-integration.xml
phpunit-integration.xml.dist
phpunit-integration-multisite.xml
phpunit-integration-multisite.xml.dist
README.md
rollup.config.js
scoper.inc.php
tsconfig.json
tsconfig.shared.json
webpack.config.cjs
webpack.config.test.cjs
================================================
FILE: .editorconfig
================================================
# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.php]
indent_style = tab
indent_size = 4
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .eslintignore
================================================
**/node_modules/**
**/vendor/**
**/dist/**
**/dist-module/**
**/dist-types/**
**/assets/js/*.js
**/packages/migration/scripts/module.js
bin/build/*
build/*
!.storybook
================================================
FILE: .eslintrc
================================================
{
"root": true,
"parser": "@babel/eslint-parser",
"extends": [
"plugin:@wordpress/eslint-plugin/i18n",
"eslint:recommended",
"plugin:import/recommended",
"plugin:@eslint-community/eslint-comments/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended-latest",
"plugin:prettier/recommended",
"plugin:jsx-a11y/recommended",
"plugin:jsdoc/recommended",
"plugin:styled-components-a11y/recommended",
"plugin:oxlint/recommended"
],
"plugins": [
"@babel",
"@wordpress",
"header",
"jsdoc",
"jsx-a11y",
"markdown",
"react",
"react-hooks",
"styled-components-a11y"
],
"parserOptions": {
"ecmaVersion": "latest",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"array-callback-return": "error",
"block-scoped-var": "error",
"complexity": ["error", {"max": 20}],
"consistent-return": "error",
"curly": ["error", "all"],
"default-case": "error",
"eol-last": "error",
"eqeqeq": "error",
"guard-for-in": "error",
"no-await-in-loop": "error",
"no-constant-binary-expression": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-floating-decimal": "error",
"no-implicit-coercion": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-loop-func": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-multiple-empty-lines": "error",
"no-trailing-spaces": "error",
"header/header": [ "error", "block", [
"",
{
"pattern": " \\* Copyright \\d{4} Google LLC",
"template": " * Copyright 2025 Google LLC"
},
" *",
" * Licensed under the Apache License, Version 2.0 (the \"License\");",
" * you may not use this file except in compliance with the License.",
" * You may obtain a copy of the License at",
" *",
" * https://www.apache.org/licenses/LICENSE-2.0",
" *",
" * Unless required by applicable law or agreed to in writing, software",
" * distributed under the License is distributed on an \"AS IS\" BASIS,",
" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
" * See the License for the specific language governing permissions and",
" * limitations under the License.",
" "
] ],
"import/no-cycle": "error",
"import/no-restricted-paths": [ "error", {
"zones": [ {
"target": "./packages/migration/src/migrations",
"from": "./packages/story-editor/src",
"except": [ "./migration/migrations" ]
}, {
"target": "./packages/story-editor/src",
"from": "./packages/story-editor/src/utils/useWhyDidYouUpdate.js"
} ]
} ],
"import/dynamic-import-chunkname": [ "error", {
"webpackChunknameFormat": "[0-9a-zA-Z-_/.[\\]]+"
} ],
"import/no-useless-path-segments": ["error", {
"noUselessIndex": true
}],
"import/no-relative-packages": "error",
"import/no-internal-modules": [ "error", {
"forbid": [ "@googleforcreators/**/*" ]
} ],
"jsx-a11y/label-has-for": "off",
"jsx-a11y/media-has-caption": [ "error", {
"audio": [ "Audio" ],
"video": [ "Video", "FadedVideo", "CropVideo", "StyledVideo" ],
"track": [ "Track" ]
}],
"no-restricted-properties": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-sequences": "error",
"no-shadow": ["error",
{
"ignoreOnInitialization": true
}
],
"no-template-curly-in-string": "error",
"no-throw-literal": "error",
"no-unmodified-loop-condition": "error",
"no-unused-vars": [
"error",
{
"ignoreRestSiblings": true
}
],
"no-useless-call": "error",
"jsx-a11y/anchor-has-content": "off",
"no-useless-concat": "error",
"no-console": "error",
"no-duplicate-imports": "error",
"no-var": "error",
"prefer-arrow-callback": [
"error",
{
"allowNamedFunctions": true
}
],
"prefer-const": "error",
"prefer-object-spread": "error",
"prefer-promise-reject-errors": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"radix": ["error", "as-needed"],
"require-await": "error",
"rest-spread-spacing": ["error", "never"],
"react/forbid-component-props": ["error", {
"forbid": ["for"]
}],
"react/jsx-key": "error",
"react/no-array-index-key": "error",
"react/no-unknown-property": [
"error",
{
"ignore": [
"amp",
"amp-boilerplate",
"amp-custom",
"animate-in",
"animate-in-delay",
"animate-in-duration",
"custom-element"
]
}
],
"react/prop-types": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": [
"error",
{
"enableDangerousAutofixThisMayCauseInfiniteLoops": false,
"additionalHooks": [
{
"test": "useSelect$",
"callbackIndex": 0
},
{
"test": "useBatchingCallback",
"callbackIndex": 0
},
{
"test": "useKeyEffectInternal",
"callbackIndex": 3
},
{
"test": "useKeyEffect",
"callbackIndex": 2
},
{
"test": "useKeyDownEffect",
"callbackIndex": 2
},
{
"test": "useKeyUpEffect",
"callbackIndex": 2
},
{
"test": "useGlobalKeyDownEffect",
"callbackIndex": 1
},
{
"test": "useGlobalKeyUpEffect",
"callbackIndex": 1
},
{
"test": "useIntersectionEffect",
"callbackIndex": 2
},
{
"test": "useResizeEffect",
"callbackIndex": 1
}
]
}
],
"react/jsx-boolean-value": "error",
"react/jsx-fragments": "error",
"react/jsx-no-literals": "error",
"react/jsx-no-useless-fragment": "error",
"react/no-unused-prop-types": "error",
"react/react-in-jsx-scope": "off",
"react/self-closing-comp": "error",
"react-hooks/config": "error",
"react-hooks/error-boundaries": "error",
"react-hooks/component-hook-factories": "error",
"react-hooks/gating": "error",
"react-hooks/globals": "error",
"react-hooks/immutability": "error",
"react-hooks/preserve-manual-memoization": "error",
"react-hooks/purity": "error",
"react-hooks/refs": "error",
"react-hooks/set-state-in-effect": "error",
"react-hooks/set-state-in-render": "error",
"react-hooks/static-components": "error",
"react-hooks/unsupported-syntax": "warn",
"react-hooks/use-memo": "error",
"react-hooks/incompatible-library": "warn",
"import/no-extraneous-dependencies": "error",
"import/no-unresolved": "error",
"import/order": [
"error",
{
"groups": [
"builtin",
["external", "unknown"],
"internal",
"parent",
"sibling",
"index"
]
}
],
"jsdoc/check-indentation": "error",
"jsdoc/check-syntax": "error",
"jsdoc/check-tag-names": ["error", {
"definedTags": [ "jest-environment" ]
}],
"jsdoc/reject-any-type": "off",
"jsdoc/reject-function-type": "off",
"jsdoc/require-jsdoc": ["off", {
"publicOnly": true
}],
"jsdoc/require-returns": "error",
"jsdoc/require-param-description": "error",
"jsdoc/tag-lines": [
"error",
"any",
{ "startLines": 1 }
],
"jsdoc/valid-types": "error",
"@eslint-community/eslint-comments/no-unused-disable": "error",
"@eslint-community/eslint-comments/require-description": "error",
"@wordpress/dependency-group": "error",
"@wordpress/i18n-no-flanking-whitespace": "error",
"@wordpress/no-unused-vars-before-return": ["error", {
"excludePattern": "^use"
}],
"@wordpress/react-no-unsafe-timeout": "error",
"@wordpress/i18n-text-domain": ["error", {
"allowedTextDomain": "web-stories"
}],
"@wordpress/valid-sprintf": "error",
"@babel/no-unused-expressions": [
"error",
{
"allowShortCircuit": true
}
]
},
"env": {
"browser": true,
"es2020": true
},
"globals": {
"__webpack_public_path__": "writable",
"WEB_STORIES_CI": "readonly",
"WEB_STORIES_DISABLE_ERROR_BOUNDARIES": "readonly",
"WEB_STORIES_DISABLE_OPTIMIZED_RENDERING": "readonly",
"WEB_STORIES_DISABLE_PREVENT": "readonly",
"WEB_STORIES_DISABLE_QUICK_TIPS": "readonly",
"WEB_STORIES_ENV": "readonly"
},
"settings": {
"import/resolver": {
"@web-stories-wp/eslint-import-resolver": {
"mapping": {
"^@googleforcreators\\/(.*)\\/(.*)": "./packages/$1/src/$2",
"^@googleforcreators\\/(.*)": "./packages/$1/src/",
"^@web-stories-wp\\/(.*)": "./packages/$1/src/"
},
"extensions": [ ".js", ".jsx", ".ts", ".tsx" ]
}
},
"jsdoc": {
"mode": "typescript",
"preferredTypes": {
"object": "Object"
},
"tagNamePreference": {
"returns": "return",
"yields": "yield"
}
},
"react": {
"version": "detect"
},
"linkComponents": [
"Link",
{"name": "Plain", "linkAttribute": "href"},
{"name": "Primary", "linkAttribute": "href"},
"PrimaryLink",
"SecondaryLink",
"ExternalLink",
"ScrimAnchor"
],
"testing-library/custom-renders": [
"arrange",
"renderWithTheme",
"renderWithProviders",
"renderPanel",
"setup"
]
},
"overrides": [
{
"files": [
"**/*.ts",
"**/*.tsx"
],
"plugins": [
"@typescript-eslint"
],
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-type-checked"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"projectService": true,
"warnOnUnsupportedTypeScriptVersion": false
},
"rules": {
"@typescript-eslint/no-shadow": ["error",
{
"ignoreOnInitialization": true
}
],
"@typescript-eslint/unbound-method": [
"error",
{
"ignoreStatic": true
}
],
"@typescript-eslint/no-unused-vars": [
"error",
{
"ignoreRestSiblings": true
}
],
"react/prop-types": "off",
"getter-return": "off",
"jsdoc/check-param-names": "off",
"jsdoc/require-param": "off",
"jsdoc/require-param-type": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-returns-check": "off",
"jsdoc/require-returns-type": "off",
"jsdoc/no-types": "error",
"no-duplicate-imports": "off",
"no-unused-vars": "off",
"no-shadow": "off",
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "prop-types",
"message": "Use TypeScript instead."
}
]
}
],
"import/no-unresolved": "off",
"import/default": "off",
"import/named": "off"
}
},
{
"files": [
"typings/**/*.ts",
"**/*.d.ts"
],
"rules": {
"no-undef": "off",
"no-unused-vars": "off",
"no-var": "off",
"@wordpress/dependency-group": "off"
}
},
{
"files": [
"__mocks__/**/*.js",
"**/test/**/*.js",
"**/test/**/*.ts",
"**/testUtils/**/*.js",
"**/testUtils/**/*.ts",
"tests/js/**/*.js"
],
"excludedFiles": [
"**/karma/**/*.js",
"**/test/**/*.karma.js"
],
"extends": [
"plugin:jest/all",
"plugin:testing-library/react",
"plugin:jest-dom/recommended",
"plugin:jest-extended/all"
],
"plugins": [
"jsx-a11y",
"header",
"testing-library",
"jest-dom"
],
"env": {
"node": true
},
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"react/prop-types": "off",
"react-hooks/globals": "off",
"react-hooks/immutability": "off",
"jest/no-hooks": "off",
"jest/no-untyped-mock-factory": "off",
"jest/max-expects": "off",
"jest/prefer-expect-assertions": "off",
"jest/prefer-importing-jest-globals": "off",
"jest/prefer-inline-snapshots": "off",
"jest/prefer-lowercase-title": [
"error",
{
"ignore": ["describe"]
}
],
"jest/prefer-mock-promise-shorthand": "off",
"jest/prefer-snapshot-hint": "off",
"jest/unbound-method": "off",
"jest/padding-around-all": "off",
"jest/padding-around-after-each-blocks": "off",
"jest/padding-around-after-all-blocks": "off",
"jest/padding-around-before-all-blocks": "off",
"jest/padding-around-before-each-blocks": "off",
"jest/padding-around-describe-blocks": "off",
"jest/padding-around-expect-groups": "off",
"jest/padding-around-test-blocks": "off",
"jest/prefer-ending-with-an-expect": "off",
"jsdoc/require-jsdoc": "off",
"testing-library/no-await-sync-events": "error",
"testing-library/no-debugging-utils": "error",
"testing-library/no-dom-import": "error"
}
},
{
"files": [
"**/test/**/*.ts",
"**/testUtils/**/*.ts"
],
"rules": {
"@typescript-eslint/unbound-method": "off",
"jest/unbound-method": "error",
"jest/no-untyped-mock-factory": "error"
}
},
{
"files": [
"__mocks__/**/*.js"
],
"rules": {
"jest/require-hook": "off"
}
},
{
"files": [
"**/karma/**/*.js",
"packages/karma-*/**/*.js"
],
"extends": [
"plugin:jasmine/recommended"
],
"plugins": [
"jsx-a11y",
"header",
"testing-library",
"jasmine"
],
"env": {
"jasmine": true,
"node": true
},
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"testing-library/no-await-sync-events": "error",
"testing-library/no-await-sync-queries": "error",
"testing-library/no-debugging-utils": "error",
"testing-library/no-dom-import": "error",
"jasmine/new-line-before-expect": "off",
"jasmine/no-disabled-tests": "error",
"jasmine/no-spec-dupes": ["error", "branch"],
"jasmine/no-suite-dupes": ["error", "branch"],
"jsdoc/require-jsdoc": "off",
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "@testing-library/react-hooks",
"message": "Use karma fixtures instead."
}
]
}
]
},
"globals": {
"karmaPuppeteer": "readonly",
"karmaSnapshot": "readonly"
}
},
{
"files": [
"packages/karma-puppeteer-client/**/*.js"
],
"rules": {
"no-var": "off",
"prefer-const": "off"
}
},
{
"files": [
"packages/jest-amp/src/**/*.js",
"packages/jest-puppeteer-amp/src/**/*.js"
],
"env": {
"node": true
}
},
{
"files": [
"packages/jest-puppeteer-amp/src/**/*.js"
],
"globals": {
"browser": "readonly",
"page": "readonly"
}
},
{
"files": [
"packages/e2e-test-utils/**/*.js",
"packages/e2e-tests/src/**/*.js"
],
"extends": [
"plugin:jest/all"
],
"env": {
"node": true
},
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"jest/max-expects": "off",
"jest/no-hooks": "off",
"jest/prefer-ending-with-an-expect": "off",
"jest/prefer-expect-assertions": "off",
"jest/prefer-importing-jest-globals": "off",
"jest/prefer-inline-snapshots": "off",
"jest/prefer-lowercase-title": [
"error",
{
"ignore": ["describe"]
}
],
"jest/require-hook": [
"error",
{
"allowedFunctionCalls": [
"minWPVersionRequired",
"withDisabledToolbarOnFrontend",
"withExperimentalFeatures",
"withPlugin",
"withRTL",
"withUser"
]
}
],
"jest/prefer-snapshot-hint": "off",
"jest/unbound-method": "off",
"jest/padding-around-all": "off",
"jest/padding-around-after-each-blocks": "off",
"jest/padding-around-after-all-blocks": "off",
"jest/padding-around-before-all-blocks": "off",
"jest/padding-around-before-each-blocks": "off",
"jest/padding-around-describe-blocks": "off",
"jest/padding-around-expect-groups": "off",
"jest/padding-around-test-blocks": "off"
},
"globals": {
"browser": "readonly",
"page": "readonly",
"wp": "readonly"
}
},
{
"files": [
"packages/e2e-test-utils/**/*.js"
],
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"jest/expect-expect": "off",
"jest/max-expects": "off",
"jest/no-export": "off",
"jest/require-top-level-describe": "off"
}
},
{
"files": ["packages/e2e-tests/src/specs/**/*.js"],
"rules": {
"jsdoc/require-jsdoc": "off"
}
},
{
"files": [
"packages/e2e-tests/src/config/**/*.js",
"**/testUtils/**/*.js"
],
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"jest/require-hook": "off"
}
},
{
"files": [
"packages/commander/**/*.ts",
"packages/fonts/scripts/**/*.ts",
"packages/migration/scripts/**/*.js",
"packages/templates/scripts/**/*.js",
"packages/text-sets/scripts/**/*.js"
],
"rules": {
"import/no-useless-path-segments": ["error", {
"noUselessIndex": false
}]
}
},
{
"files": [
"__mocks__/**/*.js",
"bin/**/*.js",
"babel.config.cjs",
"rollup.config.js",
"jest-puppeteer.config.cjs",
"karma-*.config.cjs",
"webpack.*.cjs",
".storybook/*.cjs",
".storybook/*.js",
"tests/js/*.js",
"packages/e2e-tests/src/*.js",
"packages/e2e-tests/src/config/*.js",
"packages/dashboard/src/karma-tests.cjs",
"packages/story-editor/src/karma-tests.cjs",
"packages/eslint-import-resolver/**/*.cjs",
"packages/jest-resolver/**/*.cjs",
"packages/fonts/**/*.ts",
"packages/commander/**/*.ts",
"packages/migration/scripts/**/*.js",
"packages/templates/scripts/**/*.js",
"packages/text-sets/scripts/**/*.js"
],
"extends": [
"plugin:n/recommended",
"plugin:security/recommended-legacy"
],
"plugins": [
"security"
],
"env": {
"node": true
},
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"n/no-extraneous-import": "off",
"n/no-missing-import": "off",
"n/no-unpublished-import": "off",
"n/no-unpublished-require": "off",
"security/detect-non-literal-fs-filename": "off"
}
},
{
"files": [
"packages/commander/src/index.ts"
],
"rules": {
"no-console": "off",
"n/hashbang": "off"
}
},
{
"files": [
"packages/migration/scripts/utils/updateTemplates.js"
],
"rules": {
"@eslint-community/eslint-comments/no-unused-disable": "off"
}
},
{
"files": [
"*.md",
"**/*.md"
],
"processor": "markdown/markdown"
},
{
"files": [
"**/*.md/*.js"
],
"parserOptions": {
"ecmaFeatures": {
"impliedStrict": true
}
},
"rules": {
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": "off",
"@wordpress/dependency-group": "off",
"no-console": "off",
"no-undef": "off",
"no-unused-vars": "off",
"header/header": "off",
"prettier/prettier": "off",
"@eslint-community/eslint-comments/require-description": "off",
"react/prop-types" : "off"
}
},
{
"files": [
"packages/dashboard/src/**/*.js",
"packages/story-editor/src/**/*.js",
"packages/**/*.js"
],
"excludedFiles": [
"packages/activation-notice/**/*.tsx",
"packages/i18n/**/*.js",
"packages/stories-block/**/*.js",
"packages/tinymce-button/**/*.js"
],
"rules":{
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "@wordpress/i18n",
"message": "Use @googleforcreators/i18n instead."
}
]
}
]
}
},
{
"files": [
"packages/activation-notice/**/*.tsx",
"packages/stories-block/**/*.js",
"packages/tinymce-button/**/*.js"
],
"rules":{
"@wordpress/data-no-store-string-literals": "error",
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "@googleforcreators/i18n",
"message": "Use @wordpress/i18n instead."
},
{
"name": "react",
"message": "Please use React API through `@wordpress/element` instead."
},
{
"name": "react-dom",
"message": "Please use React API through `@wordpress/element` instead."
}
]
}
]
}
},
{
"files": [
"packages/**/*.js"
],
"excludedFiles": [
".storybook/preview.js",
"__mocks__/**/*.js",
"packages/activation-notice/**/*.tsx",
"packages/react/**/*.js",
"packages/dashboard/src/karma/fixture.js",
"packages/story-editor/src/karma/fixture/fixture.js",
"packages/story-block/**/*.js",
"packages/tinymce-button/**/*.js"
],
"rules":{
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "react",
"message": "Use @googleforcreators/react instead."
},
{
"name": "react-dom",
"message": "Use @googleforcreators/react instead."
}
]
}
]
}
},
{
"files": [
"packages/activation-notice/**/*.tsx"
],
"rules":{
"no-restricted-imports": "off",
"import/no-named-as-default": "off",
"@typescript-eslint/no-restricted-imports": [
"error",
{
"paths": [
{
"name": "react",
"message": "Use @wordpress/element instead.",
"allowTypeImports": true
},
{
"name": "react-dom",
"message": "Use @wordpress/element instead.",
"allowTypeImports": true
}
]
}
]
}
},
{
"files": [
"packages/tinymce-button/src/**/*.js"
],
"globals": {
"tinymce": "readonly"
}
},
{
"files": [
"**/stories/*.js",
".storybook/main.cjs"
],
"rules": {
"react/no-array-index-key" : "off",
"react/prop-types": "off",
"@eslint-community/eslint-comments/no-unused-disable": "off",
"@eslint-community/eslint-comments/require-description": "off"
}
},
{
"files": [
"__mocks__/**/*",
".storybook/stories/**/*"
],
"rules": {
"import/no-extraneous-dependencies" : "off"
}
},
{
"files": [
"packages/story-editor/src/**/*.js",
"packages/dashboard/src/**/*.js"
],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": [
"**/*.css"
],
"message": "css import is not allowed in story-editor and dashboard"
}
]
}
]
}
},
{
"files": [
"packages/date/src/third_party/**/*"
],
"rules": {
"header/header": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unsafe-return": "off"
}
},
{
"files": [
"packages/story-editor/src/components/canvas/mediaCaptions/cue.js"
],
"rules": {
"@eslint-community/eslint-comments/no-unused-disable": "off"
}
},
{
"files": [
"packages/design-system/src/components/keyboard/keyboard.tsx",
"packages/element-library/src/media/editCropMoveable.tsx",
"packages/element-library/src/media/editPanMoveable.tsx",
"packages/element-library/src/text/edit.tsx",
"packages/element-library/src/video/playPauseButton.tsx",
"packages/react/src/useBatchingCallback.ts",
"packages/react/src/useResizeEffect.ts",
"packages/story-editor/src/app/helpCenter/provider.tsx",
"packages/story-editor/src/app/media/media3p/useContextValueProvider.js",
"packages/story-editor/src/app/media/media3p/useFetchMediaEffect.js",
"packages/story-editor/src/app/quickActions/useQuickActions.js",
"packages/story-editor/src/components/canvas/mediaRecordingLayer.js",
"packages/story-editor/src/components/canvas/multiSelectionMoveable/useDrag.js",
"packages/story-editor/src/components/canvas/multiSelectionMoveable/useResize.js",
"packages/story-editor/src/components/canvas/multiSelectionMoveable/useRotate.js",
"packages/story-editor/src/components/canvas/singleSelectionMoveable/index.js",
"packages/story-editor/src/components/canvas/singleSelectionMoveable/useDrag.js",
"packages/story-editor/src/components/canvas/singleSelectionMoveable/useResize.js",
"packages/story-editor/src/components/canvas/singleSelectionMoveable/useRotate.js",
"packages/story-editor/src/components/canvas/utils/useUpdateSelectionRectangle.js",
"packages/story-editor/src/components/colorPicker/editablePreview.js",
"packages/story-editor/src/components/form/usePresubmitHandler.js",
"packages/story-editor/src/components/library/panes/shopping/shoppingPane.js",
"packages/story-editor/src/components/mediaRecording/audio.js",
"packages/story-editor/src/components/mediaRecording/footer.js",
"packages/story-editor/src/components/panels/shared/useCommonObjectValue.js",
"packages/story-editor/src/components/videoTrim/useVideoNode.js",
"packages/transform/src/useTransformHandler.ts",
"packages/wp-story-editor/src/components/fontCheck/index.js"
],
"rules": {
"react-hooks/refs": "off"
}
}
]
}
================================================
FILE: .git-blame-ignore-revs
================================================
bf0cb0583153e71fcceaee044550ad511b94d470
1e93c55d2c9e596404646a3bd1785f6249f9945c
fe28ba3ced458b23fc53574bb25d6d3fbe6a4b3f
e6594d05a23cbd026f51668adc652fda959febbb
f459efbc4a2c9546a0ca2fed1301e4f222fa2340
72c8fa5e2419876f20507240314d0acbb825059d
================================================
FILE: .gitattributes
================================================
*.snap linguist-generated=true
.github export-ignore
.storybook export-ignore
.wordpress-org export-ignore
__mocks__ export-ignore
__static__ export-ignore
bin export-ignore
karma export-ignore
patches export-ignore
tests export-ignore
.* export-ignore
*.config.cjs export-ignore
*.config.test.cjs export-ignore
codecov.yml export-ignore
package.json export-ignore
package-lock.json export-ignore
percy.config.yml export-ignore
*.xml.dist export-ignore
packages/fonts/src/fonts.json linguist-generated=true
includes/data/fonts/fonts.json linguist-generated=true
tests/phpunit/integration/data/schema.json linguist-generated=true
packages/e2e-tests/src/specs/editor/shopping/schema.json linguist-generated=true
tsconfig.json linguist-language=jsonc
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug Report
about: Create a report to help us improve.
title: ''
labels: 'Type: Bug'
assignees: ''
---
<!--
NOTE: For help requests, support questions, or general feedback,
please use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/
-->
## Bug Description
<!-- A clear and concise description of what the bug is. -->
## Expected Behaviour
<!-- Please describe clearly and concisely what the expected behaviour should be. -->
## Steps to Reproduce
<!-- Please provide detailed steps on how to reproduce the bug. -->
## Screenshots
<!--
If applicable, please add screenshots to help explain your problem.
Bonus points for videos!
-->
## Additional Context
<!-- Please complete the following information. -->
- Plugin Version:
- WordPress Version:
- Operating System:
- Browser:
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
# todo: disable in future?
blank_issues_enabled: true
================================================
FILE: .github/ISSUE_TEMPLATE/enhancement.md
================================================
---
name: Enhancement
about: Suggest an idea for this project.
title: ''
labels: 'Type: Enhancement'
assignees: ''
---
<!-- NOTE: For help requests, support questions, or general feedback, please use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/ -->
## Feature Description
<!-- A clear and concise description of what the problem is and what you want to happen. -->
## Alternatives Considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
## Additional Context
<!-- Add any other context or screenshots about the feature request. -->
================================================
FILE: .github/ISSUE_TEMPLATE/epic.md
================================================
---
name: Epic
about: A theme of work that contains several issues or sub-tasks.
title: ''
labels: 'Epic'
assignees: ''
---
## Summary
<!-- A brief description of what this feature or collection of work should accomplish. -->
## References
<!-- List any relevant links here e.g. mocks in Figma, product or engineering briefs, etc. -->
## Alternatives Considered
<!-- What alternative solutions to the proposal have we considered, if any? What were their trade-offs? -->
## Acceptance Criteria
### Does this epic have any performance impact?
<!-- How might this epic affect user-perceived performance? -->
<!-- After implementation, did you verify that there any impact? Was it positive, neutral or regressive? -->
### Does this epic have telemetry?
<!-- Should we collect usage metrics or other instrumentation data for this epic? -->
================================================
FILE: .github/ISSUE_TEMPLATE/task.md
================================================
---
name: Task
about: Tasks which do not involve engineering.
title: ''
labels: 'Type: Task'
assignees: ''
---
<!-- NOTE: For help requests, support questions, or general feedback, please use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/ -->
## Task Description
<!-- A clear and concise description of what this task is about. -->
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Summary
<!-- A brief description of what this PR does. -->
## User-facing changes
<!--
Please describe your changes.
Include before/after screenshots or a short video.
-->
## Testing Instructions
<!--
How can the changes in this PR be verified?
Please provide step-by-step instructions how to reproduce the issue, if applicable.
Write step-by-step test instructions aimed at non-tech-savvy users, even if the PR is not user-facing.
-->
<!-- ignore-task-list-start -->
- [ ] This is a non-user-facing change and requires no QA
<!-- ignore-task-list-end -->
This PR can be tested by following these steps:
1.
## Reviews
### Does this PR have a security-related impact?
<!-- Examples: new APIs, changes to KSES, etc. -->
### Does this PR change what data or activity we track or use?
<!-- Examples: changes to telemetry, new third-party APIs -->
### Does this PR have a legal-related impact?
<!-- Examples: new images with unknown sources, new production dependencies with incompatible licenses -->
## Checklist
<!-- Check these after PR creation -->
- [ ] This PR addresses an existing issue and I have linked this PR to it
- [ ] I have tested this code to the best of my abilities
- [ ] I have verified accessibility to the best of my abilities ([docs](https://github.com/googleforcreators/web-stories-wp/blob/main/docs/accessibility-testing.md))
- [ ] I have verified i18n and l10n (translation, right-to-left layout) to the best of my abilities
- [ ] This code is covered by automated tests (unit, integration, and/or e2e) to verify it works as intended ([docs](https://github.com/googleforcreators/web-stories-wp/tree/main/docs#testing))
- [ ] I have added documentation where necessary
- [ ] I have added a matching `Type: XYZ` label to the PR
---
<!--
Please reference the issue(s) this PR addresses.
No URLs, just the issue numbers.
Use "Fixes #123" if it fixes an issue.
NOTE: One reference per line!
Example:
Fixes #123
Partially addresses #456
See #789
-->
Fixes #
================================================
FILE: .github/SUPPORT.md
================================================
Thank you for being an early adopter of Web Stories for WordPress! We're working around the clock to improve your experience and add editing capabilities. If you find any issues, please reach out by visiting the [support forum](https://wordpress.org/support/plugin/web-stories/) to ask any questions or file feature requests.
[Visit support forums](https://wordpress.org/support/plugin/web-stories/)
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
schedule:
interval: quarterly
open-pull-requests-limit: 10
labels:
- Dependencies
groups:
github-actions:
patterns:
- '*'
- package-ecosystem: npm
directory: '/'
schedule:
interval: quarterly
open-pull-requests-limit: 15
labels:
- Dependencies
- JavaScript
groups:
wp-packages:
patterns:
- '@wordpress/*'
exclude-patterns:
- '@wordpress/element'
storybook:
patterns:
- 'storybook'
- '@storybook/*'
typescript-eslint:
patterns:
- '@typescript-eslint/*'
babel:
patterns:
- 'babel-*'
- '@babel/*'
exclude-patterns:
- 'babel-plugin-react-compiler'
oxlint:
patterns:
- 'oxlint'
- 'eslint-plugin-oxlint'
react-compiler:
patterns:
- '*-react-compiler'
- 'react-compiler-*'
ignore:
# styled-components is not yet compatible.
- dependency-name: 'stylis-plugin-rtl'
versions:
- '>= 2'
# Not all plugins are compatible yet
- dependency-name: 'rollup'
versions:
- '>= 3'
# We have not yet upgraded to React 18.
- dependency-name: 'react'
versions:
- '>= 18'
- dependency-name: 'react-dom'
versions:
- '>= 18'
- dependency-name: '@testing-library/react'
versions:
- '>= 13'
# ESM only
- dependency-name: 'use-context-selector'
versions:
- '>= 2'
- dependency-name: 'flagged'
versions:
- '>= 3'
- dependency-name: 'mime'
versions:
- '>= 4'
# Needs manual update
- dependency-name: 'styled-components'
versions:
- '>= 6'
# Needs manual update
- dependency-name: 'eslint'
versions:
- '>= 9'
- package-ecosystem: composer
directory: '/'
schedule:
interval: quarterly
open-pull-requests-limit: 10
labels:
- Dependencies
- PHP
================================================
FILE: .github/release.yml
================================================
changelog:
exclude:
authors:
- dependabot
- github-actions
- googleforcreators-bot
categories:
- title: '🚀 Features'
labels:
- 'Type: Enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'Type: Bug'
- title: '🧰 Maintenance'
labels:
- 'Type: Infrastructure'
- 'Type: Code Quality'
- title: ':memo: Documentation'
labels:
- 'Type: Documentation'
- title: 'Other Changes'
labels:
- '*'
================================================
FILE: .github/workflows/build-and-deploy.yml
================================================
name: Build plugin
on:
push:
# Don't run for irrelevant changes.
paths-ignore:
- 'docs/**'
- '.storybook/**'
- '.wordpress-org/**'
- '__mocks__/**'
- '__static__/**'
- 'bin/**'
- 'packages/e2e-test-utils/**'
- 'packages/e2e-tests/**'
- 'packages/karma-*/**'
- 'tests/**'
- '**.md'
- '**.yml'
- '**.neon.dist'
- '**.xml.dist'
- '.editorconfig'
- '.eslint*'
- '.markdownlint*'
- '.phpstorm.meta.php'
- '.prettier*'
- '.stylelint*'
- '.github/workflows/**'
- '!.github/workflows/build-and-deploy.yml'
branches:
- main
- release/*
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
# Don't run for irrelevant changes.
paths-ignore:
- 'docs/**'
- '.storybook/**'
- '.wordpress-org/**'
- '__mocks__/**'
- '__static__/**'
- 'bin/**'
- 'packages/e2e-test-utils/**'
- 'packages/e2e-tests/**'
- 'packages/karma-*/**'
- 'tests/**'
- '**.md'
- '**.yml'
- '**.neon.dist'
- '**.xml.dist'
- '.editorconfig'
- '.eslint*'
- '.markdownlint*'
- '.phpstorm.meta.php'
- '.prettier*'
- '.stylelint*'
- '.github/workflows/**'
- '!.github/workflows/build-and-deploy.yml'
permissions:
contents: read
pull-requests: write
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
bundle-size:
name: Bundle size check
runs-on: ubuntu-latest
timeout-minutes: 15
# The action cannot annotate the PR when run from a PR fork or authored by Dependabot.
if: >
github.event_name == 'pull_request' &&
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.fork == false &&
github.event.pull_request.user.login != 'dependabot[bot]'
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: block
allowed-endpoints: >
cloudresourcemanager.googleapis.com:443
codeserver.dev.6b7f1eeb-705b-4201-864d-2007030c8372.drush.in:2222
dl.google.com:443
github.com:443
api.github.com:443
oauth2.googleapis.com:443
objects.githubusercontent.com:443
packagist.org:443
registry.npmjs.org:443
storage.googleapis.com:443
54.185.253.63:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Bundle size check
uses: preactjs/compressed-size-action@66325aad6443cb7cf89c4bfcd414aea2367cda94
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pattern: '{assets/js/*.js,assets/css/*.css}'
build-script: 'build:js'
minimum-change-threshold: 100
# Ignore chunk and module hashes in bundle filenames.
strip-hash: '.*-(\w{20})|^(\d{2,5})\.js$'
================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
name: CodeQL
on:
push:
# Only run if JS files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
branches:
- main
- release/*
pull_request:
# Only run if JS files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
# The branches below must be a subset of the branches above
branches:
- main
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Initialize CodeQL
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13
with:
languages: javascript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13
================================================
FILE: .github/workflows/deploy-storybook.yml
================================================
name: Deploy to GH Pages
on:
push:
# Don't run for irrelevant changes.
paths-ignore:
- 'docs/**'
- '!.github/workflows/deploy-storybook.yml'
- '.storybook/**'
- '.wordpress-org/**'
- '__mocks__/**'
- '__static__/**'
- 'bin/**'
- 'tests/**'
branches:
- main
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build-storybook:
name: Build storybook
runs-on: ubuntu-latest
permissions:
contents: write # for Git to git push
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Build storyook
run: npm run storybook:build
- name: Checkout gh-pages
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
ref: gh-pages
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
path: gh-pages
- name: Move storybook assets
run: |
rm -rf gh-pages/storybook/*
mv build/storybook/* gh-pages/storybook/
- name: Commit updates
run: |
git add .
git status
git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 0
git commit -m "Deploy storybook for ${{ github.sha }}"
git pull --rebase --no-edit --quiet
git push origin gh-pages
env:
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
working-directory: ./gh-pages
================================================
FILE: .github/workflows/lint-css-js-md.yml
================================================
name: Lint CSS/JS/MD
on:
push:
# Only run if CSS/JS/MD-related files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**.css'
- 'docs/**/*.md'
- 'packages/**/*.md'
- '.eslint*'
- '.markdownlint*'
- '.npmpackagejsonlintrc.json'
- '.nvmrc'
- '.prettier*'
- '.stylelint*'
- '**/package.json'
- 'package-lock.json'
branches:
- main
- release/*
pull_request:
# Only run if CSS/JS/MD-related files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**.css'
- 'docs/**/*.md'
- 'packages/**/*.md'
- '.eslint*'
- '.markdownlint*'
- '.npmpackagejsonlintrc.json'
- '.nvmrc'
- '.prettier*'
- '.stylelint*'
- '**/package.json'
- 'package-lock.json'
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
permissions:
checks: write # for ataylorme/eslint-annotate-action to create checks
contents: read # for actions/checkout to fetch code
pull-requests: read # for ataylorme/eslint-annotate-action to get changed PR files
timeout-minutes: 20
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-sudo: true
disable-file-monitoring: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
github.com:443
registry.npmjs.org:443
bun.sh:443
54.185.253.63:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Markdown Lint
run: npm run lint:md
- name: CSS Lint
run: npm run lint:css
- name: package.json Lint
run: npm run lint:package-json
# Do this first so that the types are available to ESLint,
# particularly the more sophisticated `@typescript/eslint` rules.
- name: Type checking
run: npm run workflow:bundle-packages:types
- name: JS Lint
run: npm run lint:js
env:
NODE_OPTIONS: --max-old-space-size=4096
if: >
github.event.pull_request.head.repo.fork == true ||
github.event.pull_request.user.login == 'dependabot[bot]'
- name: JS Lint Report
run: npm run lint:js:report
continue-on-error: true
env:
NODE_OPTIONS: --max-old-space-size=4096
# Prevent generating the ESLint report if PR is from a fork or authored by Dependabot.
if: >
github.event.pull_request.head.repo.fork == false &&
github.event.pull_request.user.login != 'dependabot[bot]'
- name: Annotate JS Lint Results
uses: ataylorme/eslint-annotate-action@3.0.0
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
report-json: 'build/lint-js-report.json'
# The action cannot annotate the PR when run from a PR fork or authored by Dependabot.
if: >
github.event.pull_request.head.repo.fork == false &&
github.event.pull_request.user.login != 'dependabot[bot]'
- name: JSON Schema validation
run: npm run test:schema
================================================
FILE: .github/workflows/lint-i18n.yml
================================================
name: Lint I18N
on:
push:
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'web-stories.php'
- 'includes/**.php'
- '.github/workflows/lint-i18n.yml'
branches:
- main
pull_request:
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'web-stories.php'
- 'includes/**.php'
- '.github/workflows/lint-i18n.yml'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
coverage: none
tools: wp-cli
- name: Install latest version of i18n-command
run: wp package install wp-cli/i18n-command:@stable
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
coverage: none
tools: composer
- name: Install dependencies
run: |
npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Build plugin
run: bun run build:js
- name: Bundle regular version
run: bun run workflow:build-plugin
# Check if as many strings as expected were found.
# Fail job if `wp i18n make-pot` returns any warnings.
# Some false positive warnings are removed due to a bug in the string extraction.
# That's why this step is unfortunately a bit more complex.
# See https://github.com/wp-cli/i18n-command/issues/154
- name: Generate POT file
run: |
OUTPUT=$((wp i18n make-pot build/web-stories build/web-stories.pot) 2>&1 >/dev/null)
HAS_ERROR=false
EXPECTED_NUMBER_OF_STRINGS=1000
NUMBER_OF_FOUND_STRINGS=$(grep -o msgstr build/web-stories.pot | wc -l | xargs)
if (( "$NUMBER_OF_FOUND_STRINGS" < "$EXPECTED_NUMBER_OF_STRINGS" )); then
HAS_ERROR=true
echo "String extraction found only $NUMBER_OF_FOUND_STRINGS translatable strings. Expected at least $EXPECTED_NUMBER_OF_STRINGS."
fi
IFS=$'\n'
declare -a WARNINGS=($OUTPUT)
unset IFS
for WARNING in "${WARNINGS[@]}"; do
# Filter false positives.
if [[ $WARNING == *"translator comment"* ]] && [[ $WARNING != *"%s"* ]]; then
continue
fi
HAS_ERROR=true
echo $WARNING
done
if [[ "$HAS_ERROR" = true ]]; then
exit 1
fi
================================================
FILE: .github/workflows/lint-php.yml
================================================
name: Lint PHP
on:
push:
# Only run if PHP-related files changed.
paths:
- '**.php'
- 'phpcs.xml.dist'
- 'phpmd.xml'
- 'phpstan.neon.dist'
- 'composer.json'
- 'composer.lock'
- '.github/workflows/lint-php.yml'
branches:
- main
- release/*
pull_request:
# Only run if PHP-related files changed.
paths:
- '**.php'
- 'phpcs.xml.dist'
- 'phpmd.xml'
- 'phpstan.neon.dist'
- 'composer.json'
- 'composer.lock'
- '.github/workflows/lint-php.yml'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
github.com:443
objects.githubusercontent.com:443
packagist.org:443
repo.packagist.org:443
getcomposer.org:443
dl.cloudsmith.io:443
54.185.253.63:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
coverage: none
tools: composer, cs2pr
- name: Validate composer.json
run: composer --no-interaction validate --no-check-all
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Detect coding standard violations (PHPCS)
run: vendor/bin/phpcs -q --report=checkstyle --severity=1 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 | cs2pr --graceful-warnings
- name: Static Analysis (PHPStan)
run: composer phpstan
- name: Static Analysis (PHPMD)
run: composer phpmd
- name: Normalize composer.json
run: composer normalize --no-interaction --dry-run
================================================
FILE: .github/workflows/lint-plugin-check.yml
================================================
name: Plugin Check
on:
push:
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'web-stories.php'
- 'includes/**.php'
- '.github/workflows/lint-plugin-check.yml'
branches:
- main
pull_request:
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'web-stories.php'
- 'includes/**.php'
- '.github/workflows/lint-plugin-check.yml'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: '8.0'
coverage: none
tools: composer
- name: Install dependencies
run: |
npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Build plugin
run: bun run build:js
- name: Bundle plugin
run: bun run workflow:build-plugin
- name: Run plugin check
uses: wordpress/plugin-check-action@v1
with:
build-dir: './build/web-stories'
exclude-directories: 'third-party'
exclude-checks: |
late_escaping
plugin_readme
plugin_review_phpcs
plugin_updater
================================================
FILE: .github/workflows/npm-release.yml
================================================
# npm packages release automation
name: npm Release
on:
workflow_dispatch:
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
env:
PRODUCTION_REGISTRY_URL: https://wombat-dressing-room.appspot.com
LOCAL_REGISTRY_URL: http://localhost:4873
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
jobs:
dry-run:
name: Dry-run release
runs-on: ubuntu-latest
timeout-minutes: 30
# This step requires additional review
# See https://docs.github.com/en/actions/reference/environments
environment: Production
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Bundle packages
run: bun run workflow:bundle-packages
env:
NODE_OPTIONS: '--max_old_space_size=4096'
# Exact format here doesn't matter for the dry-run, it's gonna be done properly later on.
- name: Version bumps
id: version_bumps
run: npm version --no-git-tag-version --workspaces "0.1.$(date -u +%Y%m%d%H%M)"
# Set up a local npm registry with Verdaccio.
- name: Set up local registry
run: bun run local-registry:start
# Using Verdaccio
- name: Publish packages locally
run: npm --registry=$LOCAL_REGISTRY_URL --workspaces publish
# Undo the version bumps in Git. We only needed them for testing.
- name: Clean up local changes
run: git checkout .
# Verifies that packages can be installed without issues.
- name: Install published packages
run: |
PUBLIC_PACKAGES=$(jq -r 'select(.private == false) | .name' $(find packages -maxdepth 2 -name "package.json"))
TMPDIR=${TMPDIR-/tmp}
TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//")
TEST_DIR=${TEST_DIR-$TMPDIR/packages-test}
mkdir $TEST_DIR
cd $TEST_DIR
npm init --yes
npm --registry=$LOCAL_REGISTRY_URL install $PUBLIC_PACKAGES
npm ls --depth 0
- name: Stop local registry
run: bun run local-registry:stop
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write # for Git to git push
timeout-minutes: 20
needs: [dry-run]
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
# See go/npm-publish
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
registry-url: ${{ env.PRODUCTION_REGISTRY_URL }}
scope: '@googleforcreators'
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Bundle packages
run: bun run workflow:bundle-packages
env:
NODE_OPTIONS: '--max_old_space_size=4096'
# For the time being, using incremental versions like 0.1.202111302140
# `npm version` updates all packages, even the ones we don't intend to publish.
# To address this, we undo the version change for private packages.
# We're doing the commit ourselves since we only need it later on and
# since committing doesn't work properly when using workspaces.
# See https://github.com/npm/cli/issues/4017
- name: Version bumps
id: version_bumps
run: |
NEW_VERSION_RAW="0.1.$(date -u +%Y%m%d%H%M)";
NEW_VERSION="v$NEW_VERSION_RAW"
npm version --no-git-tag-version --workspaces $NEW_VERSION_RAW
# Undo changes to all the private packages.
for package_file in ./packages/*/package.json; do
if [[ $(cat $package_file | jq '.private') == true ]]; then
git checkout --quiet $package_file
fi
done
# Updates the lock file.
npm install
git add packages/*/package.json
git add package-lock.json
echo "Committing version bump"
echo
git commit -m "Bumping npm packages version to $NEW_VERSION"
echo "Adding tags"
echo
# For every public package, this creates a tag in the form "<package>-v1234".
# Example: templates-v1234
for package_file in ./packages/*/package.json; do
if [[ $(cat $package_file | jq '.private') == false ]]; then
package_name=$(basename $(dirname $package_file))
echo "Adding tag: $package_name-$NEW_VERSION"
git tag "$package_name-$NEW_VERSION"
fi
done
echo "Commit details:"
echo
git status
git log -n 1
echo "Added tags:"
echo
git tag --points-at HEAD
echo "Changed files:"
echo
git show --pretty=%gd --stat
git push origin main --tags
# Do the actual publishing to npmjs.com via Wombat Dressing Room.
- name: Publish packages to production
run: npm --registry=$PRODUCTION_REGISTRY_URL --workspaces publish --workspaces
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
================================================
FILE: .github/workflows/plugin-release.yml
================================================
# Plugin release automation
#
# Builds the plugin for release candidates and stable releases.
#
# Creates the release branch, the actual release on GitHub, and the correct tag.
#
# For new major releases, the action should be run from the `main` branch.
# For patch releases, the action should be run from the corresponding release branch (e.g. `release/1.2.0`)
name: Plugin Release
on:
workflow_dispatch:
inputs:
version:
description: 'Plugin version (e.g. 1.2.3 or 7.2.0-rc.1)'
required: true
permissions:
contents: read
env:
PLUGIN_VERSION: ${{ github.event.inputs.version }}
TAG_NAME: 'v${{ github.event.inputs.version }}'
IS_RC: ${{ contains(github.event.inputs.version, 'rc') }}
IS_PATCH_RELEASE: ${{ startsWith(github.ref, 'refs/heads/release/') }}
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
GITHUB_REPO_ID: 235435637
jobs:
# Perform some sanity checks at the beginning to avoid surprises.
checks:
name: Checks
runs-on: ubuntu-latest
timeout-minutes: 5
# This step requires additional review
# See https://docs.github.com/en/actions/reference/environments
environment: Production
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Verify semver compatibility
run: |
if [[ $PLUGIN_VERSION =~ $SEMVER_VERSION_REGEX ]]; then
echo "Given plugin version string is a valid semver version"
else
echo "Given plugin version string is not a valid semver version"
exit 1
fi
env:
SEMVER_VERSION_REGEX: ^([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?(\+[0-9A-Za-z-]+)?$
- name: Verify release does not exist yet
run: |
if git describe --abbrev=0 --tags --match "$TAG_NAME" &>/dev/null; then
echo "The planned plugin version already exists!"
exit 1
fi
# - name: Ensure RC exists for stable release
# if: ${{ ! contains(github.event.inputs.version, 'rc') }}
# run: |
# VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}
# BRANCH=release/$VERSION_WITHOUT_SUFFIX
#
# if [[ -z $(git ls-remote origin $BRANCH) ]]; then
# echo "No release branch exists for this planned stable release"
# exit 1
# fi
#
# git checkout --track origin/$BRANCH
#
# if ! git describe --abbrev=0 --tags --match "$TAG_NAME-rc.*" &>/dev/null; then
# echo "No RC exists for this planned stable release"
# exit 1
# fi
- name: Ensure readme.txt contains changelog
run: |
VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}
CHANGELOG_REGEX="= $VERSION_WITHOUT_SUFFIX ="
if ! grep -q -P "$CHANGELOG_REGEX" readme.txt; then
echo "No changelog found in readme.txt"
exit 1
fi
# Get the current CDN assets version.
# If the static assets on the CDN have changed since the last release,
# bump the assets version accordingly in the GoogleForCreators/wp.stories.google repo.
assets-version:
name: Prepare static assets
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [checks]
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
# TODO: Define behavior for patch releases.
#
# A patch release is done from a specific release branch instead of `main`
#
# Patch releases must not necessarily copy assets from `main`.
# Given the following assets versions:
# main 1 2 3 4 <- next major release
# ^
# |
# current branch
#
# The patch release should probably get version 3.1 or similar,
# since version 4 is already used by the next major release.
#
# Right now, this is needs to be done manually for patch releases,
# otherwise the assets version is left unchanged here.
# Grab current assets version from `web-stories.php` and pass on to next steps.
# - name: Checkout
# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
# with:
# ref:
# - name: Get current assets version
# id: base_assets_version
# run: |
# BASE_ASSETS_VERSION=main
# if [[ $(cat web-stories.php) =~ $ASSETS_VERSION_REGEX ]]; then
# BASE_ASSETS_VERSION=${BASH_REMATCH[1]}
# fi
# echo "BASE_ASSETS_VERSION=$BASE_ASSETS_VERSION" >> $GITHUB_OUTPUT
# env:
# ASSETS_VERSION_REGEX: "https://wp.stories.google/static/([^']+)"
- name: Checkout wp.stories.google
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
repository: GoogleForCreators/wp.stories.google
lfs: true
# Needed so the below commits will trigger a website deployment.
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Authenticate
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Setup Cloud SDK
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
# For release candidates of new major releases:
#
# 1. Get highest assets version
# 2. Compare with `main`
# 3. If they differ:
# 3.1 Set new_version = version+1
# 3.2 Copy `main` to new_version
# 3.2 Push new directory
# 4. Else, keep currently highest version
- name: Prepare assets for RC
if: ${{ contains(github.event.inputs.version, 'rc') && ! startsWith(github.ref, 'refs/heads/release/') }}
run: |
LATEST_ASSETS_VERSION=$(gcloud storage ls gs://web-stories-wp-cdn-assets/ | sed 's/gs:\/\/web-stories-wp-cdn-assets\///' | sed 's/\///' | sort -n | tail -1)
NEW_ASSETS_VERSION=$LATEST_ASSETS_VERSION
NUMBER_OF_NEW_ASSETS=$(ls main | wc -l)
if [[ "0" -eq NUMBER_OF_NEW_ASSETS ]]; then
echo "No new assets found. Not uploading anything."
else
echo "New assets found."
NEW_ASSETS_VERSION=$((LATEST_ASSETS_VERSION+1))
echo "Copying existing assets over to new version."
gcloud storage rsync -r gs://web-stories-wp-cdn-assets/$LATEST_ASSETS_VERSION gs://web-stories-wp-cdn-assets/$NEW_ASSETS_VERSION
echo "Uploading new assets to new version."
gcloud storage rsync main gs://web-stories-wp-cdn-assets/$NEW_ASSETS_VERSION --recursive --ignore-symlinks --exclude="(^|/)\."
rm -rf main/*
echo "Updating LATEST_ASSETS_VERSION Firebase env variable."
echo "LATEST_ASSETS_VERSION=$NEW_ASSETS_VERSION" > ../../packages/functions/.env
git add ../../packages/functions/.env
git add .
git status
git commit -m "Preparing assets for plugin release $PLUGIN_VERSION"
git pull --rebase
git push origin main
fi
echo "Assets version for this release: $NEW_ASSETS_VERSION"
mkdir -p assets_version
echo $NEW_ASSETS_VERSION > assets_version/assets_version.txt
echo "ASSETS_VERSION=${NEW_ASSETS_VERSION}" >> $GITHUB_ENV
working-directory: public/static
env:
BASE_ASSETS_VERSION: main
# Uploads an empty file just so we have something to download in the next step
# Essentially a no-op.
- name: Prepare assets for stable release
if: ${{ ! contains(github.event.inputs.version, 'rc') || startsWith(github.ref, 'refs/heads/release/') }}
run: |
mkdir -p assets_version
echo "" > assets_version/assets_version.txt
- name: Upload assets version
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: assets-version
path: public/static/assets_version
- name: Write summary
run: |
echo "Preparing assets for release" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Assets version: $ASSETS_VERSION" >> $GITHUB_STEP_SUMMARY
env:
ASSETS_VERSION: ${{ env.ASSES_VERSION }}
build:
name: Build new version
runs-on: ubuntu-latest
timeout-minutes: 20
needs: [assets-version]
outputs:
release_branch: ${{ steps.release_branch.outputs.release_branch }}
release_name: ${{ steps.release_branch.outputs.release_name }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0 # 0 indicates all history for all branches and tags.
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Download assets version
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: assets-version
continue-on-error: true
- name: Retrieve assets version
id: assets_version
run: |
echo "ASSETS_VERSION=$(cat assets_version.txt)" >> $GITHUB_ENV
rm -rf assets_version.txt
continue-on-error: true
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
coverage: none
tools: composer
- name: Install dependencies
run: |
npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Create release branch
id: release_branch
run: |
VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}
BRANCH=release/$VERSION_WITHOUT_SUFFIX
# Patch releases are already on the correct branch.
if $IS_PATCH_RELEASE; then
BRANCH=${GITHUB_REF#refs/heads/}
echo "release_branch=${BRANCH}" >> $GITHUB_OUTPUT
exit 0
fi
if [[ -z $(git ls-remote origin $BRANCH) ]]; then
git checkout -b $BRANCH
else
git checkout --track origin/$BRANCH
fi
echo "release_branch=${BRANCH/-rc./ RC}" >> $GITHUB_OUTPUT
RELEASE_NAME=${PLUGIN_VERSION/-rc./ RC}
echo "release_name=${RELEASE_NAME}" >> $GITHUB_OUTPUT
- name: Update assets version
run: bun run workflow:assets-version $ASSETS_VERSION
if: ${{ env.ASSETS_VERSION }}
env:
ASSETS_VERSION: ${{ env.ASSETS_VERSION }}
- name: Commit assets version bump
run: |
git add web-stories.php
git status
git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 0
git commit -m "Update assets version to $ASSETS_VERSION"
git push -u origin HEAD
if: ${{ env.ASSETS_VERSION }}
env:
ASSETS_VERSION: ${{ env.ASSETS_VERSION }}
- name: Update plugin version
run: bun run workflow:version $PLUGIN_VERSION
# Commit the plugin version bump if it was successful.
# It's also possible that there were no changes, for example if the
# workflow was run a second time and the commit has already happened,
# but the process later failed.
# This allows re-running the workflow again without aborting in this case.
- name: Commit plugin version bump
id: plugin_version_bump
run: |
git add web-stories.php
git status
if git diff --cached --exit-code > /dev/null; then
git commit -m "Prepare release $PLUGIN_VERSION"
git push -u origin HEAD
echo "changes=yes" >> $GITHUB_ENV
else
echo 'No changes to commit; exiting!'
echo "changes=no" >> $GITHUB_ENV
fi
# Only non-patch release version bumps should be cherry picked to main
# This will cherry-pick the last commit from the release branch, as
# we only want the plugin version bump, not the assets version bump.
#
# Cherry-picking is only done if there actually was
# a version bump in the previous step.
- name: Cherry-pick to main
run: |
git checkout main
git cherry-pick $BRANCH
git pull --rebase
git push
git checkout $BRANCH
if: ${{ ! startsWith(github.ref, 'refs/heads/release/') && env.changes == 'yes' }}
env:
BRANCH: ${{ steps.release_branch.outputs.release_branch }}
- name: Build plugin
run: bun run build:js
- name: Bundle regular version
run: bun run workflow:build-plugin -- --zip web-stories.zip
- name: Bundle development version
run: |
rm -rf assets/css/* assets/js/*
npx webpack --env=development
bun run workflow:build-plugin -- --zip web-stories-dev.zip
- name: Prepare release artifacts
run: |
mkdir -p build/release-assets
mv build/*.zip build/release-assets/
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: release-assets
path: build/release-assets
create-release:
name: Create Release
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [build]
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Download release artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: release-assets
path: build
- name: Publish Release
id: create_release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
with:
tag_name: ${{ env.TAG_NAME }}
name: ${{ env.release_name }}
target_commitish: ${{ steps.release_branch.outputs.release_branch || github.ref }}
prerelease: ${{ env.IS_RC }}
generate_release_notes: true
files: |
build/web-stories.zip
build/web-stories-dev.zip
fail_on_unmatched_files: true
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
# Post-release version bumps for non-patch releases.
post-release:
name: Post-release version bump
needs: [create-release]
runs-on: ubuntu-latest
if: ${{ ! startsWith(github.ref, 'refs/heads/release/') && ! contains(github.event.inputs.version, 'rc') }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
ref: main
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
# If we're releasing 1.6.0, bump version on main to 1.7.0-alpha.0.
- name: Update plugin version
run: npm run workflow:version -- --increment preminor --preid alpha
- name: Commit changes
run: |
git add web-stories.php
git status
git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 1
git commit -m "Post-release version bump"
git pull --rebase
git push -u origin HEAD
# Stable releases are automatically deployed to WordPress.org.
# TODO: Consider also deploying other types of releases (RC, beta), but without bumping the stable tag.
# This way we could offer users a way to beta test the plugin.
# See http://plugins.svn.wordpress.org/buddypress/tags/ and https://wordpress.org/plugins/bp-beta-tester/ for inspiration.
deploy:
name: Deploy plugin to WordPress.org
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [create-release]
if: ${{ ! contains(github.event.inputs.version, 'rc') }}
env:
PLUGIN_REPO_URL: 'https://plugins.svn.wordpress.org/web-stories'
STABLE_TAG_REGEX: 'Stable tag:\s*(.+)'
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Download release artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: release-assets
path: release-assets
- name: Install svn
run: |
sudo apt update -y --allow-releaseinfo-change
sudo apt install -y subversion
- name: Check out trunk folder
run: svn checkout $PLUGIN_REPO_URL svn --username "$SVN_USERNAME"
- name: Get previous stable tag
id: get_previous_stable_tag
# Returns the whole matching line.
run: echo stable_tag=$(grep -P "$STABLE_TAG_REGEX" ./svn/trunk/readme.txt) >> $GITHUB_ENV
- name: Delete everything in trunk
run: find . -maxdepth 1 -not -name ".svn" -not -name "." -not -name ".." -exec rm -rf {} +
working-directory: ./svn/trunk
- name: Unzip release asset into trunk
run: |
unzip release-assets/web-stories.zip
mv web-stories/* svn/trunk
env:
PLUGIN_URL: ${{ github.event.release.assets[0].browser_download_url }}
- name: Replace stable tag placeholder with pre-existing stable tag
run: |
sed -r -i "s/${STABLE_TAG_REGEX}/${STABLE_TAG}/g" ./readme.txt
working-directory: ./svn/trunk
env:
STABLE_TAG: ${{ env.stable_tag }}
# Note: Creating the tag trigger an email confirmation that needs to be confirmed by someone with commit access.
- name: Commit changes to trunk
run: |
svn st | grep '^?' | awk '{print $2}' | xargs -r svn add
svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm
svn commit -m "Committing version $PLUGIN_VERSION" \
--no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
working-directory: ./svn
# Copy trunk to the new tag directly on the server.
# Not done in the same commit as the changes to trunk in order to reduce number of file operations
# and to prevent potential timeouts.
# See https://developer.wordpress.org/plugins/wordpress-org/how-to-use-subversion/#create-tags-from-trunk
- name: Create the SVN tag
run: |
svn cp "$PLUGIN_REPO_URL/trunk" "$PLUGIN_REPO_URL/tags/$PLUGIN_VERSION" \
-m "Tagging version $PLUGIN_VERSION" \
--no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
working-directory: ./svn
# It's recommended to run this only after the tag was successfully created.
# Otherwise, if there were any errors, we risk changing this to a tag that doesn't exist.
# The actual release still needs to be confirmed via email.
- name: Update stable tag
working-directory: ./svn
run: |
sed -r -i "s/${STABLE_TAG_REGEX}/Stable tag: ${PLUGIN_VERSION}/g" ./trunk/readme.txt
svn commit -m "Releasing version $PLUGIN_VERSION" \
--no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
================================================
FILE: .github/workflows/scorecards.yml
================================================
name: Scorecards supply-chain security
on:
# Only the default branch is supported.
branch_protection_rule:
schedule:
- cron: '0 12 1 * *'
push:
branches: [main]
permissions:
contents: read
jobs:
analysis:
name: Scorecards analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
actions: read
contents: read
# Needed to access OIDC token.
id-token: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: 'Checkout code'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a
with:
results_file: results.sarif
results_format: sarif
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
# Publish the results to enable scorecard badges. For more details, see
# https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories, `publish_results` will automatically be set to `false`,
# regardless of the value entered here.
publish_results: true
# Upload the results as artifacts (optional).
- name: 'Upload artifact'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13
with:
sarif_file: results.sarif
================================================
FILE: .github/workflows/tests-e2e.yml
================================================
name: E2E Tests
on:
push:
# Don't run for irrelevant changes.
paths-ignore:
- 'docs/**'
- '.storybook/**'
- '.wordpress-org/**'
- '__mocks__/**'
- '__static__/**'
- 'tests/**'
- '**.md'
- '**.yml'
- '**.neon.dist'
- '**.xml.dist'
- 'readme.txt'
- '.editorconfig'
- '.eslint*'
- '.markdownlint*'
- '.phpstorm.meta.php'
- '.prettier*'
- '.stylelint*'
- '.github/workflows/**'
- '!.github/workflows/tests-e2e.yml'
branches:
- main
- release/*
pull_request:
# Don't run for irrelevant changes.
paths-ignore:
- 'docs/**'
- '.storybook/**'
- '.wordpress-org/**'
- '__mocks__/**'
- '__static__/**'
- 'tests/**'
- '**.md'
- '**.yml'
- '**.neon.dist'
- '**.xml.dist'
- 'readme.txt'
- '.editorconfig'
- '.eslint*'
- '.markdownlint*'
- '.phpstorm.meta.php'
- '.prettier*'
- '.stylelint*'
- '.github/workflows/**'
- '!.github/workflows/tests-e2e.yml'
types:
- opened
- reopened
- synchronize
- ready_for_review
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build plugin
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
coverage: none
tools: composer
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Build plugin
run: bun run build:js
env:
# TODO: remove eventually
DISABLE_PREVENT: true
DISABLE_QUICK_TIPS: true
- name: Bundle plugin
run: bun run workflow:build-plugin
- name: Upload bundle
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: web-stories
path: build/web-stories
e2e:
name: '${{ matrix.browser }} - WP ${{ matrix.wp }} (${{ matrix.shard }})'
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: ${{ matrix.experimental == true }}
needs: [build]
strategy:
fail-fast: false
matrix:
# TODO: add back Firefox once support is more mature.
browser: ['chrome']
wp: ['6.6']
snapshots: [false]
experimental: [false]
# We want to split up the tests into 2 parts running in parallel.
shard: ['1/2', '2/2']
include:
- browser: 'chrome'
wp: 'latest'
snapshots: true
shard: '1/2'
- browser: 'chrome'
wp: 'latest'
snapshots: true
shard: '2/2'
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: audit
allowed-endpoints: >
github.com:443
objects.githubusercontent.com:443
packagist.org:443
registry.npmjs.org:443
storage.googleapis.com:443
docker.io:443
registry-1.docker.io:443
auth.docker.io:443
34.104.35.123:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Download bundle
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: web-stories
# See https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix
- name: Install libgbm1
run: sudo apt-get install libgbm1
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_PRODUCT: ${{ matrix.browser }}
- name: Start Docker environment
run: npm run env:start
env:
COMPOSE_INTERACTIVE_NO_CLI: true
WP_VERSION: ${{ matrix.wp }}
# See https://issues.chromium.org/issues/373753919
# and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- name: Disable AppArmor
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
- name: Get Chromium executable path
id: chromium_path
run: |
CHROMIUM=$(node -p "const puppeteer = require('puppeteer'); puppeteer.executablePath();")
echo "chromium_path=${CHROMIUM}" >> $GITHUB_ENV
if: ( matrix.snapshots ) && ( github.event.pull_request.draft == false )
- name: Download AMP validator JS
id: amp_validator
run: |
cd $RUNNER_TEMP && curl -O -f -s -S https://cdn.ampproject.org/v0/validator_wasm.js
AMP_VALIDATOR_FILE="${RUNNER_TEMP}/validator_wasm.js"
echo "validator_file=$AMP_VALIDATOR_FILE" >> $GITHUB_ENV
- name: Run E2E tests
run: npm run test:e2e -- --shard=$SHARD
env:
WP_VERSION: ${{ matrix.wp }}
SHARD: ${{ matrix.shard }}
AMP_VALIDATOR_FILE: ${{ env.validator_file }}
- name: Stop Docker environment
run: npm run env:stop
if: always()
env:
COMPOSE_INTERACTIVE_NO_CLI: true
- name: Get artifact name
if: always()
run: |
ARTIFACT_NAME=${ARTIFACT_NAME//\//-}
echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
env:
ARTIFACT_NAME: failures-artifacts-${{ matrix.wp }}-${{ matrix.shard }}
- name: Upload artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
if: always()
with:
name: ${{ env.ARTIFACT_NAME }}
path: build/e2e-artifacts
if-no-files-found: ignore
================================================
FILE: .github/workflows/tests-karma-dashboard.yml
================================================
name: Dashboard Integration Tests
on:
push:
# Only run if dashboard-related files changed.
paths:
- 'babel.config.cjs'
- 'karma-dashboard.config.cjs'
- 'webpack.config.cjs'
- 'webpack.config.test.cjs'
- 'packages/**/*.js'
- 'packages/**/*.ts'
- 'packages/**/*.tsx'
- '**/package.json'
- 'package-lock.json'
- '__static__/**'
branches:
- main
- release/*
pull_request:
# Only run if dashboard-related files changed.
paths:
- 'babel.config.cjs'
- 'karma-dashboard.config.cjs'
- 'webpack.config.cjs'
- 'webpack.config.test.cjs'
- 'packages/**/*.js'
- 'packages/**/*.ts'
- 'packages/**/*.tsx'
- '**/package.json'
- 'package-lock.json'
- '__static__/**'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
karma:
name: Karma
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
codecov.io:443
fonts.googleapis.com:443
fonts.gstatic.com:443
github.com:443
registry.npmjs.org:443
storage.googleapis.com:443
uploader.codecov.io:443
www.gravatar.com:443
54.185.253.63:443
34.104.35.123:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
# TODO: Remove need for `npm install puppeteer`.
- name: Install dependencies
run: |
npm ci
npm install puppeteer
env:
PUPPETEER_PRODUCT: chrome
# See https://issues.chromium.org/issues/373753919
# and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- name: Disable AppArmor
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
# FIXME: https://github.com/googleforcreators/web-stories-wp/issues/4364
- name: Increase max number of file watchers
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- name: Get Chromium executable path
id: chromium_path
run: |
CHROMIUM=$(node -p "const puppeteer = require('puppeteer'); puppeteer.executablePath();")
echo "chromium_path=${CHROMIUM}" >> $GITHUB_ENV
- name: Run integration tests
run: npm run test:karma:dashboard -- --headless --viewport=1600:1000 --coverage || npm run test:karma:dashboard:retry-failed -- --headless --viewport=1600:1000
env:
DISABLE_ERROR_BOUNDARIES: true
- name: Upload code coverage report
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2
with:
files: build/logs/karma-coverage/dashboard/lcov.info
flags: karmatests
token: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .github/workflows/tests-karma-editor.yml
================================================
name: Editor Integration Tests
on:
push:
# Only run if editor-related files changed.
paths:
- 'babel.config.cjs'
- 'karma-story-editor.config.cjs'
- 'webpack.config.cjs'
- 'webpack.config.test.cjs'
- 'packages/**/*.js'
- 'packages/**/*.cjs'
- 'packages/**/*.ts'
- 'packages/**/*.tsx'
- '**/package.json'
- 'package-lock.json'
- '__static__/**'
- '.github/workflows/tests-karma-editor.yml'
branches:
- main
- release/*
pull_request:
# Only run if editor-related files changed.
paths:
- 'babel.config.cjs'
- 'karma-story-editor.config.cjs'
- 'webpack.config.cjs'
- 'webpack.config.test.cjs'
- 'packages/**/*.js'
- 'packages/**/*.cjs'
- 'packages/**/*.ts'
- 'packages/**/*.tsx'
- '**/package.json'
- 'package-lock.json'
- '__static__/**'
- '.github/workflows/tests-karma-editor.yml'
types:
- opened
- reopened
- synchronize
- ready_for_review
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
karma:
name: Karma (${{ matrix.shard }})
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
# We want to split up the tests into 20 parts running in parallel.
shard:
[
'1/20',
'2/20',
'3/20',
'4/20',
'5/20',
'6/20',
'7/20',
'8/20',
'9/20',
'10/20',
'11/20',
'12/20',
'13/20',
'14/20',
'15/20',
'16/20',
'17/20',
'18/20',
'19/20',
'20/20',
]
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
codecov.io:443
fonts.googleapis.com:443
fonts.gstatic.com:443
github.com:443
registry.npmjs.org:443
storage.googleapis.com:443
uploader.codecov.io:443
wp.stories.google:443
media3p.googleapis.com:443
stories.local:80
54.185.253.63:443
34.104.35.123:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
# TODO: Remove need for `npm install puppeteer`.
- name: Install dependencies
run: |
npm ci
npm install puppeteer
env:
PUPPETEER_PRODUCT: chrome
# See https://issues.chromium.org/issues/373753919
# and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- name: Disable AppArmor
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
# FIXME: https://github.com/googleforcreators/web-stories-wp/issues/4364
- name: Increase max number of file watchers
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- name: Get Chromium executable path
id: chromium_path
run: |
CHROMIUM=$(node -p "const puppeteer = require('puppeteer'); puppeteer.executablePath();")
echo "chromium_path=${CHROMIUM}" >> $GITHUB_ENV
- name: Run integration tests
run: |
npm run test:karma:story-editor -- --headless --viewport=1600:1000 --coverage --shard=$SHARD || \
npm run test:karma:story-editor:retry-failed -- --headless --viewport=1600:1000 --shard=$SHARD
env:
DISABLE_ERROR_BOUNDARIES: true
SHARD: ${{ matrix.shard }}
- name: Upload code coverage report
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2
with:
files: build/logs/karma-coverage/story-editor/lcov.info
flags: karmatests
token: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .github/workflows/tests-unit-js.yml
================================================
name: JavaScript Unit Tests
on:
push:
# Only run if JS-related files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'packages/templates/src/raw/**'
- 'packages/text-sets/src/raw/**'
- 'patches/**'
- 'packages/fonts/src/fonts.json'
branches:
- main
- release/*
pull_request:
# Only run if JS-related files changed.
paths:
- '**.js'
- '**.cjs'
- '**.ts'
- '**.tsx'
- '**/package.json'
- 'package-lock.json'
- 'packages/templates/src/raw/**'
- 'packages/text-sets/src/raw/**'
- 'patches/**'
- 'packages/fonts/src/fonts.json'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
unit-js:
name: Unit Tests (${{ matrix.shard }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
# We want to split up the tests into 2 parts running in parallel.
shard: ['1/2', '2/2']
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-sudo: true
disable-file-monitoring: true
egress-policy: audit
allowed-endpoints: >
cdn.ampproject.org:443
codecov.io:443
github.com:443
raw.githubusercontent.com:443
registry.npmjs.org:443
storage.googleapis.com:443
uploader.codecov.io:443
fonts.gstatic.com:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Setup Jest cache
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7
with:
path: .jest-cache
key: ${{ runner.os }}-${{ env.NVMRC }}-jest
# Rollup is needed for tests in `packages/migration/src` expecting `module.js`
- name: Install dependencies
run: |
npm ci
npx rollup --config packages/migration/rollup.config.js
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Download AMP validator JS
id: amp_validator
run: |
cd $RUNNER_TEMP && curl -O -f -s -S https://cdn.ampproject.org/v0/validator_wasm.js
AMP_VALIDATOR_FILE="${RUNNER_TEMP}/validator_wasm.js"
echo "validator_file=$AMP_VALIDATOR_FILE" >> $GITHUB_ENV
- name: Run JavaScript unit tests
run: npm run test:js -- --runInBand --ci --cacheDirectory="$HOME/.jest-cache" --collectCoverage --shard=$SHARD
env:
SHARD: ${{ matrix.shard }}
AMP_VALIDATOR_FILE: ${{ env.validator_file }}
- name: Upload code coverage report
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2
with:
files: build/logs/lcov.info
flags: unittests
token: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .github/workflows/tests-unit-php.yml
================================================
name: PHP Unit Tests
on:
push:
# Only run if PHP-related files changed.
paths:
- '**.php'
- 'phpunit.xml.dist'
- 'phpunit-multisite.xml.dist'
- 'composer.json'
- 'composer.lock'
- 'tests/phpunit/**'
- 'includes/data/**'
- '.github/workflows/tests-unit-php.yml'
branches:
- main
- release/*
pull_request:
# Only run if PHP-related files changed.
paths:
- '**.php'
- 'phpunit.xml.dist'
- 'phpunit-multisite.xml.dist'
- 'composer.json'
- 'composer.lock'
- 'tests/phpunit/**'
- 'includes/data/**'
- '.github/workflows/tests-unit-php.yml'
permissions:
contents: read
# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the (target) branch name.
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
unit-php:
name: PHP ${{ matrix.php }} - WP ${{ matrix.wp }}${{ matrix.experimental && ' (experimental)' || '' }}${{ matrix.coverage && ' (with coverage)' || '' }}${{ matrix.random && ' (in random order)' || '' }}
runs-on: ubuntu-latest
timeout-minutes: 20
services:
mysql:
image: mariadb:lts
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: wordpress_test
MARIADB_MYSQL_LOCALHOST_USER: 1
MARIADB_MYSQL_LOCALHOST_GRANTS: USAGE
ports:
- 3306
options: --health-cmd="healthcheck.sh --su-mysql --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3
continue-on-error: ${{ matrix.experimental }}
strategy:
matrix:
php: ['8.4', '8.3', '8.2', '8.1', '8.0']
wp: ['latest']
coverage: [false]
experimental: [false]
include:
- php: '8.5'
wp: 'latest'
coverage: true
experimental: false
- php: '8.5'
wp: 'latest'
random: true
experimental: true
- php: '7.4'
wp: '6.6'
experimental: false
- php: '8.5'
wp: 'trunk'
experimental: true
- php: 'nightly'
wp: 'trunk'
experimental: true
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
disable-file-monitoring: true
egress-policy: audit
allowed-endpoints: >
api.github.com:443
api.wordpress.org:80
cdn.ampproject.org:443
develop.svn.wordpress.org:443
example.com:443
github.com:443
objects.githubusercontent.com:443
packagist.org:443
raw.github.com:443
repo.packagist.org:443
wordpress.org:443
getcomposer.org:443
dl.cloudsmith.io:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
# PHP-Scoper only works on PHP 7.4+ and we need to prefix our dependencies to accurately test them.
# So we temporarily switch PHP versions, do a full install and then remove the package.
# Then switch back to the PHP version we want to test and delete the vendor directory.
- name: Setup PHP 8.0
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: latest
tools: composer
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction'
- name: Remove prefixed dependencies
run: rm -rf vendor/*
- name: Setup PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f
with:
php-version: ${{ matrix.php }}
extensions: mysql
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
tools: composer, cs2pr
- name: Install PHP dependencies
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda
with:
composer-options: '--prefer-dist --no-progress --no-interaction --no-scripts'
- name: Composer dump autoload
run: composer dump-autoload --no-interaction
- name: Shutdown default MySQL service
run: sudo service mysql stop
- name: Verify MariaDB connection
run: |
while ! mysqladmin ping -h"127.0.0.1" -P"${JOB_SERVICES_MYSQL_3307TH_PORTS}" --silent; do
sleep 1
done
env:
JOB_SERVICES_MYSQL_3307TH_PORTS: ${{ job.services.mysql.ports[3306] }}
- name: Install svn
run: |
sudo apt update -y --allow-releaseinfo-change
sudo apt install -y subversion
- name: Set up tests
run: bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1:${JOB_SERVICES_MYSQL_PORTS_3306} ${{ matrix.wp }} true
env:
JOB_SERVICES_MYSQL_PORTS_3306: ${{ job.services.mysql.ports['3306'] }}
- name: Set up problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Run tests
run: |
npm run test:php:unit
npm run test:php:integration:single
npm run test:php:integration:multisite
if: ${{ ! matrix.coverage && ! matrix.random }}
- name: Run tests with coverage
run: |
npm run test:php:unit -- --coverage-clover build/logs/php-coverage.xml
npm run test:php:integration:single -- --coverage-clover build/logs/php-coverage-integration.xml
npm run test:php:integration:multisite -- --coverage-clover build/logs/php-coverage-multisite.xml
if: ${{ matrix.coverage && ! matrix.random }}
- name: Run tests in random order
run: |
npm run test:php:unit -- --order-by random
npm run test:php:integration:single -- --order-by random
npm run test:php:integration:multisite -- --order-by random
if: ${{ matrix.random }}
- name: Upload code coverage report
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2
with:
files: build/logs/*.xml
token: ${{ secrets.CODECOV_TOKEN }}
if: ${{ matrix.coverage }}
================================================
FILE: .github/workflows/update-browserslist.yml
================================================
name: Update browserslist db
on:
workflow_dispatch:
schedule:
- cron: '0 12 1 * *'
permissions:
contents: read
env:
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
jobs:
update-browserslist-db:
name: Update browserslist db
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Update db
run: npx update-browserslist-db@latest
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
commit-message: Update browserslist db
title: Update browserslist db
body: Updates `caniuse-lite` to use the latest browser’s versions and statistics.
branch: update/browserslist-db
labels: Dependencies
================================================
FILE: .github/workflows/update-google-fonts.yml
================================================
name: Update Google Fonts
on:
workflow_dispatch:
schedule:
- cron: '0 12 1 * *'
permissions:
contents: read
env:
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
jobs:
update-fonts:
name: Update Google Fonts
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: Update list of Google Fonts
env:
GOOGLE_FONTS_API_KEY: ${{ secrets.GOOGLE_FONTS_API_KEY }}
run: npm run workflow:fonts
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
commit-message: Update list of Google Fonts
title: Update list of Google Fonts
body: Fetched the currently available fonts on Google Fonts to update them in the project.
branch: update/google-fonts
labels: Dependencies
================================================
FILE: .github/workflows/update-product-schema.yml
================================================
name: Update Product Schema
on:
workflow_dispatch:
schedule:
- cron: '0 12 1 * *'
permissions:
contents: read
env:
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
jobs:
update-fonts:
name: Update Product Schema
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Update Product Schema
run: |
curl -O -f https://raw.githubusercontent.com/ampproject/amphtml/main/examples/amp-story/shopping/product.schema.json
cp product.schema.json packages/e2e-tests/src/specs/editor/shopping/schema.json
mv product.schema.json tests/phpunit/integration/data/schema.json
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
commit-message: Update Product Schema
title: Update Product Schema
body: |
Fetched the current [product JSON schema](https://github.com/ampproject/amphtml/blob/main/examples/amp-story/shopping/product.schema.json) for `<amp-story-shopping>` to update it in the project.
branch: update/product-schema
labels: Dependencies
================================================
FILE: .github/workflows/update-templates.yml
================================================
name: Migrate Templates
on:
workflow_dispatch:
schedule:
- cron: '0 12 * * 1'
env:
GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_AUTHOR_NAME: googleforcreators-bot
GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com
GIT_COMMITTER_NAME: googleforcreators-bot
permissions:
contents: read
jobs:
update-template:
name: Migrate templates and text sets
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden Runner
uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install dependencies
run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: true
- name: Update story data (templates, text sets, FTUE)
run: npm run workflow:migrate
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}
commit-message: Migrate templates and text sets to latest version
title: Migrate templates and text sets
body: Update templates and text sets after running through migration
branch: update/templates
labels: Dependencies
================================================
FILE: .gitignore
================================================
.rollup.cache
.test_artifacts
.idea/
.vscode/
.DS_Store
node_modules
/assets
/packages/migration/scripts/module.js
/packages/*/dist
/packages/*/dist-module
/packages/*/dist-types
/build
/bin/build
/bin/local-env/data
bin/local-env/docker-compose.override.yml
/includes/vendor
/includes/composer.json
/plugin-assets
/public
/static
/third-party
/vendor
phpcs.xml
phpunit.xml
.phpunit.result.cache
/packages/*/package-lock.json
*.tsbuildinfo
================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
# TODO: Move to ~/.huskyrc instead.
# See https://typicode.github.io/husky/#/?id=command-not-found
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
. "$(dirname "$0")/_/husky.sh"
npx lint-staged --relative
================================================
FILE: .markdownlint.json
================================================
{
"default": true,
"MD003": { "style": "atx" },
"MD007": { "indent": 4 },
"MD013": { "line_length": 9999 },
"no-hard-tabs": false,
"no-inline-html": false,
"whitespace": false
}
================================================
FILE: .markdownlintignore
================================================
.github
__mocks__
assets
bin
build
node_modules
tests
vendor
================================================
FILE: .npmpackagejsonlintrc.json
================================================
{
"rules": {
"bin-type": "error",
"bundledDependencies-type": "error",
"config-type": "error",
"cpu-type": "error",
"dependencies-type": "error",
"description-type": "error",
"devDependencies-type": "error",
"directories-type": "error",
"engines-type": "error",
"files-type": "error",
"homepage-type": "error",
"keywords-type": "error",
"license-type": "error",
"main-type": "error",
"man-type": "error",
"name-format": "error",
"name-type": "error",
"no-restricted-dependencies": "off",
"no-restricted-devDependencies": "off",
"no-restricted-pre-release-dependencies": "off",
"no-restricted-pre-release-devDependencies": "off",
"optionalDependencies-type": "error",
"os-type": "error",
"peerDependencies-type": "error",
"prefer-absolute-version-dependencies": "off",
"prefer-absolute-version-devDependencies": "off",
"prefer-alphabetical-bundledDependencies": "error",
"prefer-alphabetical-dependencies": "error",
"prefer-alphabetical-devDependencies": "error",
"prefer-alphabetical-optionalDependencies": "error",
"prefer-alphabetical-peerDependencies": "error",
"prefer-caret-version-dependencies": "off",
"prefer-caret-version-devDependencies": "off",
"prefer-no-engineStrict": "off",
"prefer-no-version-zero-dependencies": "off",
"prefer-no-version-zero-devDependencies": "off",
"prefer-property-order": [
"error",
[
"name",
"description",
"private",
"version",
"author",
"license",
"keywords",
"homepage",
"repository",
"bugs",
"engines",
"files",
"type",
"workspaces",
"customExports",
"exports",
"main",
"module",
"types",
"source",
"publishConfig",
"sideEffects",
"dependencies",
"devDependencies",
"peerDependencies",
"bin",
"scripts"
]
],
"prefer-tilde-version-dependencies": "off",
"prefer-tilde-version-devDependencies": "off",
"preferGlobal-type": "error",
"private-type": "error",
"repository-type": "error",
"require-author": "error",
"require-bin": "off",
"require-bugs": "error",
"require-bundledDependencies": "off",
"require-config": "off",
"require-contributors": "off",
"require-cpu": "off",
"require-dependencies": "off",
"require-description": "error",
"require-devDependencies": "off",
"require-directories": "off",
"require-engines": "off",
"require-files": "off",
"require-homepage": "error",
"require-keywords": "error",
"require-license": "error",
"require-main": "off",
"require-man": "off",
"require-module": "off",
"require-name": "error",
"require-optionalDependencies": "off",
"require-os": "off",
"require-peerDependencies": "off",
"require-preferGlobal": "off",
"require-private": "off",
"require-publishConfig": "off",
"require-repository": "error",
"require-repository-directory": "off",
"require-scripts": "off",
"require-version": "off",
"scripts-type": "error",
"valid-values-author": ["error", ["Google"]],
"valid-values-license": ["error", ["Apache-2.0"]],
"valid-values-private": "off",
"version-format": "error",
"version-type": "error"
}
}
================================================
FILE: .npmrc
================================================
save-exact = false
lockfile-version=3
================================================
FILE: .nvmrc
================================================
24
================================================
FILE: .oxlintrc.json
================================================
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "error",
"nursery": "error",
"pedantic": "error",
"perf": "off",
"restriction": "error",
"suspicious": "error"
},
"plugins": [
"import",
"jsdoc",
"promise",
"react-perf"
],
"ignorePatterns": [
"@types"
],
"settings": {
"jsdoc": {
"tagNamePreference": {
"returns": "return",
"yields": "yield"
}
}
},
"rules": {
"accessor-pairs": "off",
"class-methods-use-this": "off",
"complexity": "off",
"default-case": "off",
"max-classes-per-file": "off",
"max-depth": "off",
"max-lines": "off",
"max-lines-per-function": "off",
"no-alert": "off",
"no-bitwise": "off",
"no-case-declarations": "off",
"no-else-return": "off",
"no-empty-function": "off",
"no-inline-comments": "off",
"no-multiple-resolved": "off",
"no-negated-condition": "off",
"no-param-reassign": "off",
"no-plusplus": "off",
"no-promise-executor-return": "off",
"no-shadow": "off",
"no-undef": "off",
"no-undefined": "off",
"no-unused-expressions": "off",
"no-unused-vars": "off",
"no-useless-return": "off",
"no-void": ["error", { "allowAsStatement": true }],
"no-warning-comments": "off",
"radix": "off",
"require-await": "off",
"sort-vars": "off",
"symbol-description": "off",
"import/export": "off",
"import/extensions": "off",
"import/max-dependencies": "off",
"import/named": "off",
"import/no-commonjs": "off",
"import/no-default-export": "off",
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"import/no-relative-parent-imports": "off",
"import/no-unassigned-import": "off",
"import/unambiguous": "off",
"jest/no-conditional-in-test": "off",
"jsdoc/check-tag-names": "off",
"jsdoc/require-param": "off",
"jsdoc/require-param-description": "off",
"jsdoc/require-param-type": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-returns-type": "off",
"promise/always-return": "off",
"promise/catch-or-return": "off",
"promise/no-callback-in-promise": "off"
},
"overrides": [
{
"files": [
"packages/commander/**/*.ts"
],
"rules": {
"no-console": "off"
}
},
{
"files": [
"**/*.d.ts",
"packages/karma-puppeteer-client/**/*.js",
"packages/karma-puppeteer-launcher/**/*.js"
],
"rules": {
"no-var": "off"
}
}
]
}
================================================
FILE: .phpstorm.config.js
================================================
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// eslint-disable-next-line no-undef -- Special global in IntelliJ.
System.config({
paths: {
// Published Packages
'@googleforcreators/animation': './packages/animation/src',
'@googleforcreators/dashboard': './packages/dashboard/src',
'@googleforcreators/date': './packages/date/src',
'@googleforcreators/design-system': './packages/design-system/src',
'@googleforcreators/dom': './packages/dom/src',
'@googleforcreators/element-library': './packages/element-library/src',
'@googleforcreators/elements': './packages/elements/src',
'@googleforcreators/fonts': './packages/fonts/src',
'@googleforcreators/i18n': './packages/i18n/src',
'@googleforcreators/masks': './packages/masks/src',
'@googleforcreators/media': './packages/media/src',
'@googleforcreators/migration': './packages/migration/src',
'@googleforcreators/moveable': './packages/moveable/src',
'@googleforcreators/output': './packages/output/src',
'@googleforcreators/patterns': './packages/patterns/src',
'@googleforcreators/react': './packages/react/src',
'@googleforcreators/rich-text': './packages/rich-text/src',
'@googleforcreators/stickers': './packages/stickers/src',
'@googleforcreators/story-editor': './packages/story-editor/src',
'@googleforcreators/templates': './packages/templates/src',
'@googleforcreators/text-sets': './packages/text-sets/src',
'@googleforcreators/tracking': './packages/tracking/src',
'@googleforcreators/transform': './packages/transform/src',
'@googleforcreators/units': './packages/units/src',
'@googleforcreators/url': './packages/url/src',
// Private Packages
'@web-stories-wp/e2e-tests': './packages/e2e-tests/src',
'@web-stories-wp/activation-notice': './packages/activation-notice/src',
'@web-stories-wp/commander': './packages/commander/src',
'@web-stories-wp/e2e-test-utils': './packages/e2e-test-utils/src',
'@web-stories-wp/eslint-import-resolver': './packages/eslint-import-resolver/src',
'@web-stories-wp/glider': './packages/glider/src',
'@web-stories-wp/jest-amp': './packages/jest-amp/src',
'@web-stories-wp/jest-puppeteer-amp': './packages/jest-puppeteer-amp/src',
'@web-stories-wp/jest-resolver': './packages/jest-resolver/src',
'@web-stories-wp/karma-failed-tests-reporter': './packages/karma-failed-tests-reporter/src',
'@web-stories-wp/karma-puppeteer-client': './packages/karma-puppeteer-client/src',
'@web-stories-wp/karma-puppeteer-launcher': './packages/karma-puppeteer-launcher/src',
'@web-stories-wp/stories-block': './packages/stories-block/src',
'@web-stories-wp/stories-carousel': './packages/stories-carousel/src',
'@web-stories-wp/tinymce-button': './packages/tinymce-button/src',
'@web-stories-wp/widget': './packages/widget/src',
'@web-stories-wp/wp-dashboard': './packages/wp-dashboard/src',
'@web-stories-wp/wp-story-editor': './packages/wp-story-editor/src',
'@web-stories-wp/wp-utils': './packages/wp-utils/src',
},
});
================================================
FILE: .phpstorm.meta.php
================================================
<?php
namespace PHPSTORM_META {
override(
\Google\Web_Stories\Services::get(),
// TODO: I'd like to use Plugin::SERVICES directly here but it doesn't seem to work.
map( [
'activation_notice' => \Google\Web_Stories\Admin\Activation_Notice::class,
'admin.google_fonts' => \Google\Web_Stories\Admin\Google_Fonts::class,
'amp_output_buffer' => \Google\Web_Stories\AMP\Output_Buffer::class,
'amp_story_player_assets' => \Google\Web_Stories\AMP_Story_Player_Assets::class,
'adsense' => \Google\Web_Stories\AdSense::class,
'ad_manager' => \Google\Web_Stories\Ad_Manager::class,
'mgid' => \Google\Web_Stories\Mgid::class,
'admin' => \Google\Web_Stories\Admin\Admin::class,
'admin.revisions' => \Google\Web_Stories\Admin\Revisions::class,
'analytics' => \Google\Web_Stories\Analytics::class,
'coi' => \Google\Web_Stories\Admin\Cross_Origin_Isolation::class,
'customizer' => \Google\Web_Stories\Admin\Customizer::class,
'dashboard' => \Google\Web_Stories\Admin\Dashboard::class,
'database_upgrader' => \Google\Web_Stories\Database_Upgrader::class,
'discovery' => \Google\Web_Stories\Discovery::class,
'editor' => \Google\Web_Stories\Admin\Editor::class,
'embed_shortcode' => \Google\Web_Stories\Shortcode\Embed_Shortcode::class,
'experiments' => \Google\Web_Stories\Experiments::class,
'integrations.amp' => \Google\Web_Stories\Integrations\AMP::class,
'integrations.ezoic' => \Google\Web_Stories\Integrations\Ezoic::class,
'integrations.jetpack' => \Google\Web_Stories\Integrations\Jetpack::class,
'integrations.newrelic' => \Google\Web_Stories\Integrations\New_Relic::class,
'integrations.nextgen_gallery' => \Google\Web_Stories\Integrations\NextGen_Gallery::class,
'integrations.cfi' => \Google\Web_Stories\Integrations\Conditional_Featured_Image::class,
'integrations.sitekit' => \Google\Web_Stories\Integrations\Site_Kit::class,
'integrations.themes_support' => \Google\Web_Stories\Integrations\Core_Themes_Support::class,
'integrations.shortpixel' => \Google\Web_Stories\Integrations\ShortPixel::class,
'kses' => \Google\Web_Stories\KSES::class,
'media.base_color' => \Google\Web_Stories\Media\Base_Color::class,
'media.blurhash' => \Google\Web_Stories\Media\Blurhash::class,
'media.image_sizes' => \Google\Web_Stories\Media\Image_Sizes::class,
'media.media_source' => \Google\Web_Stories\Media\Media_Source_Taxonomy::class,
'media.video.captions' => \Google\Web_Stories\Media\Video\Captions::class,
'media.cropping' => \Google\Web_Stories\Media\Cropping::class,
'media.video.muting' => \Google\Web_Stories\Media\Video\Muting::class,
'media.video.optimization' => \Google\Web_Stories\Media\Video\Optimization::class,
'media.video.poster' => \Google\Web_Stories\Media\Video\Poster::class,
'media.video.trimming' => \Google\Web_Stories\Media\Video\Trimming::class,
'font_post_type' => \Google\Web_Stories\Font_Post_Type::class,
'page_template_post_type' => \Google\Web_Stories\Page_Template_Post_Type::class,
'plugin_row_meta' => \Google\Web_Stories\Admin\PluginRowMeta::class,
'plugin_action_links' => \Google\Web_Stories\Admin\PluginActionLinks::class,
'product_meta' => \Google\Web_Stories\Shopping\Product_Meta::class,
'meta_boxes' => \Google\Web_Stories\Admin\Meta_Boxes::class,
'settings' => \Google\Web_Stories\Settings::class,
'site_health' => \Google\Web_Stories\Admin\Site_Health::class,
'story_archive' => \Google\Web_Stories\Story_Archive::class,
'story_post_type' => \Google\Web_Stories\Story_Post_Type::class,
'story_revisions' => \Google\Web_Stories\Story_Revisions::class,
'story_shortcode' => \Google\Web_Stories\Shortcode\Stories_Shortcode::class,
'svg' => \Google\Web_Stories\Media\SVG::class,
'tracking' => \Google\Web_Stories\Tracking::class,
'tinymce' => \Google\Web_Stories\Admin\TinyMCE::class,
'register.widget' => \Google\Web_Stories\Register_Widget::class,
'renderer.archives' => \Google\Web_Stories\Renderer\Archives::class,
'renderer.single' => \Google\Web_Stories\Renderer\Single::class,
'renderer.oembed' => \Google\Web_Stories\Renderer\Oembed::class,
'renderer.feed' => \Google\Web_Stories\Renderer\Feed::class,
'user.capabilities' => \Google\Web_Stories\User\Capabilities::class,
'rest.embed_controller' => \Google\Web_Stories\REST_API\Embed_Controller::class,
'rest.link_controller' => \Google\Web_Stories\REST_API\Link_Controller::class,
'rest.hotlinking_controller' => \Google\Web_Stories\REST_API\Hotlinking_Controller::class,
'rest.publisher_logos' => \Google\Web_Stories\REST_API\Publisher_Logos_Controller::class,
'rest.status_check_controller' => \Google\Web_Stories\REST_API\Status_Check_Controller::class,
'rest.stories_autosave' => \Google\Web_Stories\REST_API\Stories_Autosaves_Controller::class,
'rest.stories_lock' => \Google\Web_Stories\REST_API\Stories_Lock_Controller::class,
'rest.media' => \Google\Web_Stories\REST_API\Stories_Media_Controller::class,
'rest.settings' => \Google\Web_Stories\REST_API\Stories_Settings_Controller::class,
'rest.users' => \Google\Web_Stories\REST_API\Stories_Users_Controller::class,
'rest.taxonomies' => \Google\Web_Stories\REST_API\Stories_Taxonomies_Controller::class,
'rest.template_autosave' => \Google\Web_Stories\REST_API\Template_Autosaves_Controller::class,
'rest.template_lock' => \Google\Web_Stories\REST_API\Template_Lock_Controller::class,
'taxonomy.category' => \Google\Web_Stories\Taxonomy\Category_Taxonomy::class,
'taxonomy.tag' => \Google\Web_Stories\Taxonomy\Tag_Taxonomy::class,
'user_preferences' => \Google\Web_Stories\User\Preferences::class,
'remove_transients' => \Google\Web_Stories\Remove_Transients::class,
'web_stories_block' => \Google\Web_Stories\Block\Web_Stories_Block::class,
'injector' => \Google\Web_Stories\Infrastructure\Injector::class,
] )
);
// For the injector, the return type should be the same as what the provided FQCN represents.
override(
\Google\Web_Stories\Infrastructure\Injector::make(),
map( [ '' => '@' ] )
);
}
================================================
FILE: .prettierignore
================================================
/.idea
/bin/local-env/uploads.ini
/bin/local-env/data
/build
/docs
/node_modules
/vendor
/assets/css
/assets/js
/assets/images
packages/karma-puppeteer-client/src/client.js
.browserslistrc
.distignore
.editorconfig
.eslintignore
.eslintrc
.gitignore
.npmrc
.nvmrc
.prettierignore
.prettierrc
.stylelintignore
.stylelintrc
.DS_Store
*.php
*.txt
*.sh
*.svg
LICENSE
composer.json
composer.lock
package.json
package-lock.json
================================================
FILE: .prettierrc
================================================
{
"plugins": ["@prettier/plugin-xml"],
"printWidth": 80,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"overrides": [
{
"files": "*.md",
"options": {
"parser": "markdown"
}
},
{
"files": [".eslintrc", ".prettierrc", ".stylelintrc", "*.json"],
"options": {
"parser": "json"
}
},
{
"files": ["*.yml", "*.neon.dist"],
"options": {
"parser": "yaml"
}
},
{
"files": ["*.xml", "*.xml.dist"],
"options": {
"parser": "xml"
}
}
]
}
================================================
FILE: .storybook/main.cjs
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
const { readFileSync } = require('fs');
const webpack = require('webpack');
const CircularDependencyPlugin = require('circular-dependency-plugin');
// eslint-disable-next-line n/no-missing-require
const { loadCsf } = require('storybook/internal/csf-tools');
/** @type { import('@storybook/react-webpack5').StorybookConfig } */
module.exports = {
stories: [
'./stories/playground/*/(index|preview).js',
'../packages/dashboard/src/**/stories/index.js',
'../packages/story-editor/src/**/stories/index.js',
'../packages/wp-dashboard/src/**/stories/index.js',
'../packages/activation-notice/src/**/stories/index.js',
'../packages/design-system/src/**/stories/index.js',
'../packages/animation/src/**/stories/*.js',
],
experimental_indexers: (indexers) => {
const createIndex = (fileName, opts) => {
const code = readFileSync(fileName, {
encoding: 'utf-8',
});
return loadCsf(code, {
...opts,
fileName,
}).parse().indexInputs;
};
return [
{
test: /stories\/.*\.js$/,
createIndex,
},
...(indexers || []),
];
},
addons: [
'@storybook/addon-a11y/register',
'@storybook/addon-webpack5-compiler-babel',
],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
core: {
disableTelemetry: true,
},
docs: {
disabled: true,
},
//eslint-disable-next-line require-await -- Negligible.
webpackFinal: async (webpackConfig) => {
// webpack < 5 used to include polyfills for node.js core modules by default.
// Prevent ModuleNotFoundError for this dependency.
webpackConfig.resolve = {
...webpackConfig.resolve,
// Fixes resolving packages in the monorepo so we use the "src" folder, not "dist".
// This should be sync'd with the config in `webpack.config.cjs`.
exportsFields: ['customExports', 'exports'],
// To make loading mediainfo.js work.
fallback: {
fs: false,
path: false,
url: false,
module: false,
assert: false,
perf_hooks: false,
crypto: false,
worker_threads: false,
},
};
// Avoid having to provide full file extension for imports.
// See https://webpack.js.org/configuration/module/#resolvefullyspecified
webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => ({
...rule,
resolve: {
...rule.resolve,
fullySpecified: false,
},
}));
// These should be sync'd with the config in `webpack.config.cjs`.
webpackConfig.plugins.push(
new webpack.DefinePlugin({
WEB_STORIES_CI: JSON.stringify(process.env.CI),
WEB_STORIES_ENV: JSON.stringify(process.env.NODE_ENV),
WEB_STORIES_DISABLE_ERROR_BOUNDARIES: JSON.stringify(
process.env.DISABLE_ERROR_BOUNDARIES
),
WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: JSON.stringify(
process.env.DISABLE_OPTIMIZED_RENDERING
),
WEB_STORIES_DISABLE_PREVENT: JSON.stringify(
process.env.DISABLE_PREVENT
),
WEB_STORIES_DISABLE_QUICK_TIPS: JSON.stringify(
process.env.DISABLE_QUICK_TIPS
),
})
);
// These should be sync'd with the config in `webpack.config.cjs`.
webpackConfig.plugins.push(
new webpack.DefinePlugin({
WEB_STORIES_CI: JSON.stringify(process.env.CI),
WEB_STORIES_ENV: JSON.stringify(process.env.NODE_ENV),
WEB_STORIES_DISABLE_ERROR_BOUNDARIES: JSON.stringify(
process.env.DISABLE_ERROR_BOUNDARIES
),
WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: JSON.stringify(
process.env.DISABLE_OPTIMIZED_RENDERING
),
WEB_STORIES_DISABLE_PREVENT: JSON.stringify(
process.env.DISABLE_PREVENT
),
WEB_STORIES_DISABLE_QUICK_TIPS: JSON.stringify(
process.env.DISABLE_QUICK_TIPS
),
})
);
webpackConfig.plugins.push(
new CircularDependencyPlugin({
// exclude detection of files based on a RegExp
exclude: /a\.js|node_modules/,
// add errors to webpack instead of warnings
failOnError: true,
// allow import cycles that include an asynchronous import,
// e.g. via import(/* webpackMode: "weak" */ 'file.js')
allowAsyncCycles: false,
// set the current working directory for displaying module paths
cwd: process.cwd(),
})
);
// Ensure SVGR is the only loader used for files with .svg extension.
const assetRule = webpackConfig.module.rules.find(({ test }) => {
if (!test) {
return false;
}
if (Array.isArray(test)) {
return test.every((t) => t.test('.svg'));
}
return test.test('.svg');
});
assetRule.exclude = /\.svg/;
webpackConfig.module.rules.unshift(
{
test: /\.svg$/,
// Use asset SVG and SVGR together.
// Not using resourceQuery because it doesn't work well with Rollup.
// https://react-svgr.com/docs/webpack/#use-svgr-and-asset-svg-in-the-same-project
oneOf: [
{
type: 'asset/inline',
include: [/inline-icons\/.*\.svg$/],
},
{
issuer: /\.[jt]sx?$/,
include: [/\/icons\/.*\.svg$/],
use: [
{
loader: '@svgr/webpack',
options: {
titleProp: true,
svgo: true,
memo: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
convertColors: {
currentColor: /^(?!url|none)/i,
},
},
},
},
'removeDimensions',
],
},
},
},
],
},
{
issuer: /\.[jt]sx?$/,
include: [/images\/.*\.svg$/],
use: [
{
loader: '@svgr/webpack',
options: {
titleProp: true,
svgo: true,
memo: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
convertColors: {
// See https://github.com/googleforcreators/web-stories-wp/pull/6361
currentColor: false,
},
},
},
},
'removeDimensions',
],
},
},
},
],
},
],
},
{
test: /\.(png|jpe?g|gif|webp)$/i,
type: 'asset/resource',
generator: {
outputPath: 'images/',
},
}
);
return webpackConfig;
},
features: {
actions: true,
backgrounds: true,
controls: false,
viewport: true,
toolbars: true,
},
};
================================================
FILE: .storybook/manager-head.html
================================================
<style>
#playground-preview {
display: none;
}
</style>
================================================
FILE: .storybook/preview-head.html
================================================
<!--
~ Copyright 2020 Google LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<link
href="https://fonts.googleapis.com/css?family=Google+Sans|Google+Sans:b|Google+Sans:500&display=swap"
rel="stylesheet"
/>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script
async
custom-element="amp-story"
src="https://cdn.ampproject.org/v0/amp-story-1.0.js"
></script>
================================================
FILE: .storybook/preview.js
================================================
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { ThemeProvider } from 'styled-components';
// eslint-disable-next-line import/no-unresolved
import { INITIAL_VIEWPORTS } from 'storybook/viewport';
import {
theme as designSystemTheme,
lightMode,
ThemeGlobals,
ModalGlobalStyle,
} from '@googleforcreators/design-system';
import { CropMoveableGlobalStyle } from '@googleforcreators/moveable';
/**
* Internal dependencies
*/
// Disable reason:
// Importing from the dashboard and story editor roots break fast refresh in storybook.
// Prevented by importing the necessary providers and configs directly.
/* eslint-disable import/no-relative-packages */
import { GlobalStyle as DashboardGlobalStyle } from '../packages/dashboard/src/theme';
import DashboardKeyboardOnlyOutline from '../packages/dashboard/src/utils/keyboardOnlyOutline';
import DashboardConfigProvider from '../packages/dashboard/src/app/config/configProvider';
import ApiProvider from '../packages/dashboard/src/app/api/apiProvider';
import EditorConfigProvider from '../packages/story-editor/src/app/config/configProvider';
/* eslint-enable import/no-relative-packages */
// @todo: Find better way to mock these.
const wp = {};
window.wp = window.wp || wp;
window.wp.media = {
controller: {
Library: {
prototype: {
defaults: {},
},
},
},
};
const { ipad, ipad10p, ipad12p } = INITIAL_VIEWPORTS;
/** @type { import('@storybook/react-webpack5').Preview } */
const preview = {
parameters: {
a11y: {
element: '#root',
config: {},
options: {},
manual: true,
},
viewport: {
viewports: {
ipad,
ipad10p,
ipad12p,
},
},
backgrounds: {
default: 'Light',
values: [
{ name: 'Light', value: '#fff', default: true },
{ name: 'Dark', value: 'rgba(0, 0, 0, 0.9)', default: true },
],
},
},
decorators: [
(Story, context) => {
const { id } = context;
// TODO(#10380): Replacement add-on for RTL feature
const isRTL = false;
const isDesignSystemStorybook = id.startsWith('designsystem');
const isDashboardStorybook = id.startsWith('dashboard');
if (isDashboardStorybook) {
return (
<ThemeProvider
theme={{
...designSystemTheme,
colors: lightMode,
}}
>
<DashboardConfigProvider
config={{
api: { stories: 'stories' },
apiCallbacks: {
getUser: () => Promise.resolve({ id: 1 }),
},
editStoryURL: 'editStory',
isRTL,
styleConstants: {
topOffset: 0,
},
}}
>
<ApiProvider>
<DashboardGlobalStyle />
<ModalGlobalStyle />
<DashboardKeyboardOnlyOutline />
{Story()}
</ApiProvider>
</DashboardConfigProvider>
</ThemeProvider>
);
}
if (isDesignSystemStorybook) {
// override darkMode colors
const dsTheme = { ...designSystemTheme, colors: lightMode };
return (
<ThemeProvider theme={dsTheme}>
<ThemeGlobals.Styles />
<ModalGlobalStyle />
{Story()}
</ThemeProvider>
);
}
return (
<ThemeProvider theme={designSystemTheme}>
<EditorConfigProvider config={{ isRTL }}>
<CropMoveableGlobalStyle />
<ModalGlobalStyle />
{Story()}
</EditorConfigProvider>
</ThemeProvider>
);
},
],
};
export default preview;
================================================
FILE: .storybook/stories/playground/dashboard/index.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { useRef, useEffect } from 'react';
import { toId } from '@storybook/csf';
import { Dashboard, InterfaceSkeleton } from '@googleforcreators/dashboard';
/**
* Internal dependencies
*/
import { GlobalStyle } from './theme';
export default {
title: 'Playground/Dashboard',
};
const linkHrefTo = (title, name) => {
const url = new URL(window.parent.location);
url.searchParams.set('path', '/story/' + toId(title, name));
return decodeURIComponent(url.href);
};
const fetchStories = () => {
const response = {
stories: {
1: {
id: 1,
status: 'publish',
title: 'Example story',
created: '2021-11-04T10:12:47',
createdGmt: '2021-11-04T10:12:47Z',
author: {
name: 'Author',
id: 1,
},
featuredMediaUrl:
'https://wp.stories.google/static/main/images/templates/food-and-stuff/page1_bg.jpg',
},
2: {
id: 2,
status: 'publish',
title: 'Example story 2',
created: '2021-12-04T10:12:47',
createdGmt: '2021-12-04T10:12:47Z',
author: {
name: 'Author',
id: 1,
},
featuredMediaUrl:
'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page8_figure.jpg',
},
},
fetchedStoryIds: [1, 2],
totalPages: 1,
totalStoriesByStatus: {
all: 2,
publish: 2,
},
};
return Promise.resolve(response);
};
// mock filter api calls
const getTaxonomies = () =>
Promise.resolve([
{
restBase: '',
restPath: '',
labels: {
allItems: 'All Categories',
notFound: 'No categories found',
searchItems: 'Search Categories',
},
},
]);
const getTaxonomyTerms = () => Promise.resolve([{ name: 'Food', id: 1 }]);
const getAuthors = () => Promise.resolve([{ name: 'Author', id: 1 }]);
/**
* Clears url hash ( Required only for storybook )
* Dashboard uses # for checking route path and story-editor uses #page,
* when returning from story-editor to dashboard in storybook, currentPath read from history package gets manipulated,
* which breaks the current path, so this custom hook is used to clear the hash before dashboard app is mounted.
*/
const useClearHash = () => {
const isHashCleaned = useRef(false);
useEffect(() => {
if (!isHashCleaned.current) {
window.location.hash = '/';
isHashCleaned.current = true;
}
}, []);
};
export const _default = {
render: function Render() {
useClearHash();
const config = {
newStoryURL: linkHrefTo('Playground/Stories Editor', 'default'),
apiCallbacks: {
fetchStories,
getTaxonomies,
getTaxonomyTerms,
getAuthors,
},
};
return (
<Dashboard config={config}>
<GlobalStyle />
<InterfaceSkeleton />
</Dashboard>
);
},
};
================================================
FILE: .storybook/stories/playground/dashboard/theme.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { createGlobalStyle } from 'styled-components';
import { themeHelpers } from '@googleforcreators/design-system';
export const GlobalStyle = createGlobalStyle`
body.web-story_page_stories-dashboard #wpbody {
${themeHelpers.scrollbarCSS};
}
`;
================================================
FILE: .storybook/stories/playground/story-editor/api/fonts.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export async function getFonts(params) {
let { default: fonts } = await import(
/* webpackChunkName: "chunk-fonts" */ '@googleforcreators/fonts/fonts.json' // eslint-disable-line import/no-internal-modules -- This is fine here.
);
fonts = fonts.map((font) => ({
id: font.family,
name: font.family,
value: font.family,
...font,
}));
if (params.include) {
const include = params.include.split(',');
fonts = fonts.filter(({ family }) => include.includes(family));
}
if (params.search) {
fonts = fonts.filter(({ family }) =>
family.toLowerCase().includes(params.search)
);
}
return fonts;
}
================================================
FILE: .storybook/stories/playground/story-editor/api/index.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Not using "export * from" because of https://github.com/storybookjs/storybook/issues/17587
export { getFonts } from './fonts';
export { getMedia } from './media';
export { saveStoryById } from './story';
================================================
FILE: .storybook/stories/playground/story-editor/api/media.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Internal dependencies
*/
import { getDummyMedia } from '../getDummyMedia';
export const getMedia = (params) => {
const dummyMedia = getDummyMedia();
const mediaResponse = {
data: dummyMedia,
headers: {
totalItems: dummyMedia.length,
totalPages: 1,
},
};
if (params.searchTerm) {
mediaResponse.data = dummyMedia.filter((media) => {
return media.alt.toLowerCase().includes(params.searchTerm.toLowerCase());
});
mediaResponse.headers.totalItems = mediaResponse.data.length;
}
return Promise.resolve(mediaResponse);
};
================================================
FILE: .storybook/stories/playground/story-editor/api/story.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { DATA_VERSION } from '@googleforcreators/migration';
/**
* Internal dependencies
*/
import {
LOCAL_STORAGE_CONTENT_KEY,
LOCAL_STORAGE_PREVIEW_MARKUP_KEY,
} from '../constants';
export const saveStoryById = ({
pages,
globalStoryStyles,
autoAdvance,
defaultPageDuration,
currentStoryStyles,
backgroundAudio,
content,
title,
excerpt,
}) => {
const storySaveData = {
title: {
raw: title,
},
excerpt: {
raw: excerpt,
},
storyData: {
version: DATA_VERSION,
pages,
autoAdvance,
defaultPageDuration,
currentStoryStyles,
backgroundAudio,
},
author: {
id: 1,
name: '',
},
stylePresets: globalStoryStyles,
permalinkTemplate: 'https://example.org/web-stories/%pagename%/',
};
window.localStorage.setItem(
LOCAL_STORAGE_CONTENT_KEY,
JSON.stringify(storySaveData)
);
window.localStorage.setItem(LOCAL_STORAGE_PREVIEW_MARKUP_KEY, content);
return Promise.resolve({});
};
================================================
FILE: .storybook/stories/playground/story-editor/constants.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const LOCAL_STORAGE_CONTENT_KEY = 'web_stories_json_content';
export const LOCAL_STORAGE_PREVIEW_MARKUP_KEY = 'web_stories_preview_markup';
================================================
FILE: .storybook/stories/playground/story-editor/getDummyMedia.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { createResource } from '@googleforcreators/media';
function createDummyImageData({
mimeType = 'image/jpeg',
src,
width,
height,
id,
title,
}) {
return createResource({
mimeType,
creationDate: '2021-10-29T11:43:38',
src,
width,
height,
id,
alt: title,
sizes: {
medium: {
file: `${title}-300x84.jpeg`,
width: 300,
height: 84,
mimeType,
sourceUrl: src,
},
large: {
file: `${title}-1024x288.jpeg`,
width: 1024,
height: 288,
mimeType,
sourceUrl: src,
},
thumbnail: {
file: `${title}-150x150.jpeg`,
width: 150,
height: 150,
mimeType,
sourceUrl: src,
},
medium_large: {
file: `${title}-768x216.jpeg`,
width: 768,
height: 216,
mimeType,
sourceUrl: src,
},
'1536x1536': {
file: `${title}-1536x432.jpeg`,
width: 1536,
height: 432,
mimeType,
sourceUrl: src,
},
'2048x2048': {
file: `${title}-2048x576.jpeg`,
width: 2048,
height: 576,
mimeType,
sourceUrl: src,
},
'post-thumbnail': {
file: `${title}-1568x441.jpeg`,
width: 1568,
height: 441,
mimeType,
sourceUrl: src,
},
'web-stories-poster-portrait': {
file: `${title}-640x853.jpeg`,
width: 640,
height: 853,
mimeType,
sourceUrl: src,
},
'web-stories-publisher-logo': {
file: `${title}-96x96.jpeg`,
width: 96,
height: 96,
mimeType,
sourceUrl: src,
},
'web-stories-thumbnail': {
file: `${title}-150x42.jpeg`,
width: 150,
height: 42,
mimeType,
sourceUrl: src,
},
full: {
file: title,
width,
height,
mimeType,
sourceUrl: src,
},
},
});
}
function createDummyVideoData({
mimeType = 'video/mp4',
src,
mediaDetails,
id,
title,
poster,
}) {
return createResource({
mimeType,
creationDate: '2021-10-29T11:56:33',
src,
width: mediaDetails.width,
height: mediaDetails.height,
poster: poster.src,
posterId: 57,
id,
length: mediaDetails.length,
bitsPerSample: mediaDetails.bitsPerSample,
alt: title,
});
}
function getDummyMedia() {
return [
createDummyImageData({
mimeType: 'image/png',
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page1_bg-alt.png',
width: 412,
height: 732,
id: 1,
title: 'Fresh and Bright 1',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page3_figure.jpg',
width: 720,
height: 844,
id: 2,
title: 'Fresh and Bright 2',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page4_bg.png',
width: 750,
height: 1334,
id: 3,
title: 'Fresh and Bright 3',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page5_figure.jpg',
width: 750,
height: 1079,
id: 4,
title: 'Fresh and Bright 4',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page7_product1.jpg',
width: 720,
height: 900,
id: 5,
title: 'Fresh and Bright 5',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page8_figure.jpg',
width: 408,
height: 544,
id: 6,
title: 'Fresh and Bright 6',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story1.jpg',
width: 720,
height: 405,
id: 7,
title: 'Fresh and Bright 7',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story2.jpg',
width: 480,
height: 720,
id: 8,
title: 'Fresh and Bright 8',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story3.jpg',
width: 480,
height: 720,
id: 9,
title: 'Fresh and Bright 9',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page1_bg.jpg',
width: 1080,
height: 1620,
id: 10,
title: 'Fresh and Bright 10',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page3_image1.jpg',
width: 1080,
height: 720,
id: 11,
title: 'Food and Stuff 1',
}),
createDummyImageData({
src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page5_bg.jpg',
width: 731,
height: 1300,
id: 12,
title: 'Food and Stuff 2',
}),
createDummyVideoData({
src: 'https://stream.mux.com/OGTmBYTMkV7Ez601cRNpH6BP10102fQu9C00/high.mp4?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InQ5UHZucm9ZY0hQNjhYSmlRQnRHTEVVSkVSSXJ0UXhKIn0.eyJleHAiOjE2MjYxNzgxMTIsImF1ZCI6InYiLCJzdWIiOiJPR1RtQllUTWtWN0V6NjAxY1JOcEg2QlAxMDEwMmZRdTlDMDAifQ.Jvddeah-XyF0AMmfYND-fFaIfgeDYW_cAuIVIXOrk2so_YalyMMAQ11YXHA1h11yKpLM-xa8xiNXazPqA0Suq1tfxHjJjEqiQOzSlPYd4visiPdTjUgT50FkwYdJrN0IldfXoS19yi3GyAd9McVFoSGCZ6qp8m_hgJ39y8FJJbOrvGtrzEvElpz1M8M1Dat3PF-BSLvFcTvCOlec9dipajxHG_2Xg-EE_vOqww6z81kC09evj5gu_A-Vz58Q-ebd08R47ybNejhE3rzMr1dCKgUikjkkQokPPQyrwVEy8zeZ68elax-ZRvDokZ2mTVPGvKIye6m_CQ-WVlG5XRjw7A',
mediaDetails: {
filesize: 1867215,
mimeType: 'video/mp4',
length: 12,
lengthFormatted: '0:12',
width: 720,
height: 406,
fileformat: 'mp4',
dataformat: 'quicktime',
audio: {
dataformat: 'mp4',
codec: 'ISO/IEC 14496-3 AAC',
sampleRate: 48000,
channels: 2,
bitsPerSample: 16,
lossless: false,
channelmode: 'stereo',
},
createdTimestamp: -2082844800,
sizes: {},
},
id: 13,
title: 'Story',
poster: {
src: 'https://image.mux.com/OGTmBYTMkV7Ez601cRNpH6BP10102fQu9C00/thumbnail.jpg?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InQ5UHZucm9ZY0hQNjhYSmlRQnRHTEVVSkVSSXJ0UXhKIn0.eyJ0aW1lIjowLCJleHAiOjMxNzE3MDYwNjg4MSwiYXVkIjoidCIsInN1YiI6Ik9HVG1CWVRNa1Y3RXo2MDFjUk5wSDZCUDEwMTAyZlF1OUMwMCJ9.WxHU2cpFdNqqiWF08KEv1g7barfbE_Nw4JDvVrtrQc9mVKiSZ6pEHpYl14NZeaBOf4Ep9MiomaegCVrD-UANhURlxWuHWFx5h7Msg74-q_ojjuZbLZtFPUdA0NA3_GTq5y0LDAeXijM7oENn_IkuDSY0fbRhRUVh-hYqCzw_OqMx7B1IxoOkkZUCHgkm9VnPdAMQRpmaanCHB8SHVRI_vIJo577DxLd88KBFP3UWK1XTvN5NYr0oPtwc82XMYUW4HrxZZTmxzLSZckxzwB7T5E6zAtXpo-xwd52yB1OUhoihlTqiOPWbntpvt9H4lFVRISLwsT39d1Tw80HF_X02eQ',
width: 1920,
height: 1080,
generated: false,
},
}),
createDummyVideoData({
src: 'https://storage.coverr.co/videos/PDolZIrwdONTFJd005VOT4qvFsyxVfB01N/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM0NDQzfQ._6LJb2Ad843im0xV4-2I2vVpDNoPiy8nPc3-3IkSSuw',
mediaDetails: {
filesize: 1510877,
mimeType: 'video/quicktime',
length: 18,
lengthFormatted: '0:18',
width: 640,
height: 360,
fileformat: 'mp4',
dataformat: 'quicktime',
createdTimestamp: -2082844800,
sizes: {},
},
id: 14,
title: 'Low',
poster: {
src: 'https://storage.coverr.co/p/PDolZIrwdONTFJd005VOT4qvFsyxVfB01N',
width: 2048,
height: 1152,
generated: false,
},
}),
createDummyVideoData({
src: 'https://storage.coverr.co/videos/qMc3OVOA8a6Q9j01T2L3pGfF029UA00OvZJ/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM3NDkwfQ.rHiHdTyik8sDuP8viRbC4ph-qjHHJ81I7kdawP2-1eQ',
mediaDetails: {
filesize: 456538,
mimeType: 'video/mp4',
length: 15,
lengthFormatted: '0:15',
width: 360,
height: 640,
fileformat: 'mp4',
dataformat: 'quicktime',
createdTimestamp: -2082844800,
sizes: {},
audio: {
bitsPerSample: 16,
channelmode: 'stereo',
channels: 2,
codec: 'ISO/IEC 14496-3 AAC',
dataformat: 'mp4',
lossless: false,
sampleRate: 48000,
},
},
id: 15,
title: 'Mountain Video',
poster: {
src: 'https://storage.coverr.co/p/qMc3OVOA8a6Q9j01T2L3pGfF029UA00OvZJ',
width: 1080,
height: 1920,
generated: false,
},
}),
createDummyVideoData({
src: 'https://storage.coverr.co/videos/XHtOLYGTnHiXVxofSdO8oTcA02vxasheL/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM3NDkwfQ.rHiHdTyik8sDuP8viRbC4ph-qjHHJ81I7kdawP2-1eQ',
mediaDetails: {
filesize: 2536304,
mimeType: 'video/mp4',
length: 27,
lengthFormatted: '0:27',
width: 640,
height: 360,
fileformat: 'mp4',
dataformat: 'quicktime',
createdTimestamp: -2082844800,
sizes: {},
audio: {
bitsPerSample: 16,
channelmode: 'stereo',
channels: 2,
codec: 'ISO/IEC 14496-3 AAC',
dataformat: 'mp4',
lossless: false,
sampleRate: 48000,
},
},
id: 16,
title: 'Beautiful Cloud Video',
poster: {
src: 'https://storage.coverr.co/p/XHtOLYGTnHiXVxofSdO8oTcA02vxasheL',
width: 1920,
height: 1080,
generated: false,
},
}),
createDummyVideoData({
src: 'https://storage.coverr.co/videos/X4pOA7IG76p95Gl3IcU3oX26S2sbGsc2/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM4Mjc3fQ.lIznWsYEFy3abrDbou1mKJivj6GzQnHO6gJ8jdisPW0',
mediaDetails: {
filesize: 1029136,
mimeType: 'video/mp4',
length: 10,
lengthFormatted: '0:10',
width: 640,
height: 360,
fileformat: 'mp4',
dataformat: 'quicktime',
createdTimestamp: -2082844800,
sizes: {},
audio: {
bitsPerSample: 16,
channelmode: 'stereo',
channels: 2,
codec: 'ISO/IEC 14496-3 AAC',
dataformat: 'mp4',
lossless: false,
sampleRate: 48000,
},
},
id: 17,
title: 'Beautiful Fire Video',
poster: {
src: 'https://storage.coverr.co/p/X4pOA7IG76p95Gl3IcU3oX26S2sbGsc2',
width: 1920,
height: 1080,
generated: false,
},
}),
];
}
export { getDummyMedia };
================================================
FILE: .storybook/stories/playground/story-editor/header/buttons/index.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import styled from 'styled-components';
import { useStory } from '@googleforcreators/story-editor';
import { CircularProgress } from '@googleforcreators/design-system';
/**
* Internal dependencies
*/
import { SaveButton } from './saveButton';
import { PreviewButton } from './preview';
const ButtonList = styled.nav`
display: flex;
justify-content: flex-end;
padding: 1em;
height: 100%;
`;
const List = styled.div`
display: flex;
align-items: center;
`;
const Space = styled.div`
width: 8px;
`;
const Spinner = styled.div`
position: absolute;
top: 0;
`;
const IconWithSpinner = styled.div`
position: relative;
`;
function Loading() {
return (
<Spinner>
<CircularProgress size={32} />
</Spinner>
);
}
function Buttons() {
const { isSaving } = useStory(
({
state: {
meta: { isSaving },
},
}) => ({ isSaving })
);
return (
<ButtonList>
<List>
<IconWithSpinner>
<PreviewButton />
{isSaving && <Loading />}
</IconWithSpinner>
<Space />
<SaveButton />
</List>
</ButtonList>
);
}
export { Buttons };
================================================
FILE: .storybook/stories/playground/story-editor/header/buttons/preview.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { hrefTo } from '@storybook/addon-links';
import { Tooltip, useStory } from '@googleforcreators/story-editor';
import {
Button,
ButtonSize,
ButtonType,
ButtonVariant,
Icons,
} from '@googleforcreators/design-system';
function PreviewButton() {
const { isSaving, saveStory } = useStory(
({
state: {
meta: { isSaving },
},
actions: { saveStory },
}) => ({
isSaving,
saveStory,
})
);
const openPreviewLink = async () => {
await saveStory();
const previewLink = await hrefTo('Playground/preview', 'default');
// Start a about:blank popup with waiting message until we complete
// the saving operation. That way we will not bust the popup timeout.
try {
const popup = window.open('about:blank', 'story-preview');
if (popup) {
popup.document.write('<!DOCTYPE html><html><head>');
popup.document.write('<title>');
popup.document.write('Generating the preview…');
popup.document.write('</title>');
popup.document.write('</head><body>');
popup.document.write('Please wait. Generating the preview…'); // Output "waiting" message.
// Force redirect to the preview URL after 5 seconds. The saving tab
// might get frozen by the browser.
popup.document.write(
`<script>
setTimeout(function() {
location.replace(${JSON.stringify(previewLink)});
}, 5000);
</script>`
);
}
} catch {
// Not interested in the error.
}
};
return (
<Tooltip title={'Preview'} hasTail>
<Button
variant={ButtonVariant.Square}
type={ButtonType.Quaternary}
size={ButtonSize.Small}
onClick={openPreviewLink}
disabled={isSaving}
>
<Icons.Eye />
</Button>
</Tooltip>
);
}
export { PreviewButton };
================================================
FILE: .storybook/stories/playground/story-editor/header/buttons/saveButton.js
================================================
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import {
Button,
ButtonSize,
ButtonType,
ButtonVariant,
useSnackbar,
} from '@googleforcreators/design-system';
import { useStory } from '@googleforcreators/story-editor';
function SaveButton() {
const { isSaving, saveStory } = useStory(
({
state: {
meta: { isSaving },
},
actions: { saveStory },
}) => ({
isSaving,
saveStory,
})
);
const { showSnackbar } = useSnackbar();
const handleSaveButton = () => {
saveStory().then(() => {
showSnackbar({
message: 'Story Saved',
});
});
};
// @todo Make the app state persistent.
return (
<Button
variant={ButtonVariant.Rectangle}
type={ButtonType.Primary}
size={ButtonSize.Small}
onClick={handleSaveButton}
disabled={isSaving}
>
{'Save'}
</Button>
);
}
export { SaveButton };
================================================
FILE: .storybook/stories/playground/story-editor/header/index.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import styled from 'styled-components';
import { HeaderTitle } from '@googleforcreators/story-editor';
/**
* Internal dependencies
*/
import { Buttons } from './buttons';
const Background = styled.header.attrs({
role: 'group',
'aria-label': 'Story canvas header',
})`
display: flex;
align-items: center;
justify-content: space-between;
background-color: ${({ theme }) => theme.colors.bg.primary};
`;
const Head = styled.div`
flex: 1 1 auto;
padding: 1em;
`;
const ButtonCell = styled.div`
grid-area: buttons;
`;
function HeaderLayout() {
return (
<Background>
<Head>
<HeaderTitle />
</Head>
<ButtonCell>
<Buttons />
</ButtonCell>
</Background>
);
}
export { HeaderLayout };
================================================
FILE: .storybook/stories/playground/story-editor/index.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import {
StoryEditor,
InterfaceSkeleton,
} from '@googleforcreators/story-editor';
import { elementTypes } from '@googleforcreators/element-library';
import { registerElementType } from '@googleforcreators/elements';
/**
* Internal dependencies
*/
import { getMedia, saveStoryById, getFonts } from './api';
import { HeaderLayout } from './header';
import { LOCAL_STORAGE_CONTENT_KEY } from './constants';
export default {
title: 'Playground/Stories Editor',
};
export const _default = {
render: function Render() {
const content = window.localStorage.getItem(LOCAL_STORAGE_CONTENT_KEY);
const story = content ? JSON.parse(content) : {};
const apiCallbacks = { saveStoryById, getMedia, getFonts };
elementTypes.forEach(registerElementType);
return (
<div style={{ height: '100vh' }}>
<StoryEditor config={{ apiCallbacks }} initialEdits={{ story }}>
<InterfaceSkeleton header={<HeaderLayout />} />
</StoryEditor>
</div>
);
},
};
================================================
FILE: .storybook/stories/playground/story-editor/preview.js
================================================
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies
*/
import { useEffect } from 'react';
/**
* Internal dependencies
*/
import { LOCAL_STORAGE_PREVIEW_MARKUP_KEY } from './constants';
export default {
title: 'Playground/preview',
};
// This is a hidden story component ( hidden via manager-head.html ), used for previewing the story-editor. Please do not remove.
function Preview() {
useEffect(() => {
const content = window.localStorage.getItem(
LOCAL_STORAGE_PREVIEW_MARKUP_KEY
);
if (content) {
document.open();
document.write(content);
document.close();
}
}, []);
return null;
}
export const _default = Preview;
================================================
FILE: .stylelintignore
================================================
.github
.storybook
.wordpress-org
__mocks__
__static__
assets
bin
blocks
build
docs
includes
node_modules
patches
public
tests
third-party
vendor
/*.js
/*.cjs
================================================
FILE: .stylelintrc
================================================
{
"extends": [
"stylelint-config-recommended"
],
"plugins": ["stylelint-prettier"],
"customSyntax": "postcss-syntax",
"rules": {
"font-family-name-quotes": null,
"font-family-no-missing-generic-family-keyword": null,
"font-weight-notation": null,
"function-name-case": null,
"prettier/prettier": true,
"selector-class-pattern": null,
"selector-type-no-unknown": [
true,
{
"ignore": ["custom-elements"],
"ignoreTypes": ["overlay", "container"]
}
],
"property-no-vendor-prefix": [
true,
{
"ignoreProperties": ["clip-path"]
}
],
"unit-no-unknown": [
true,
{
"ignoreUnits": ["/^`/", "/`$/"]
}
],
"value-keyword-case": null
},
"overrides": [
{
"files": ["*.js", ".ts", ".tsx"],
"customSyntax": "postcss-styled-syntax",
"rules": {
"annotation-no-unknown": null,
"block-no-empty": null,
"function-no-unknown": null,
"media-query-no-invalid": null,
"no-empty-source": null
}
}
]
}
================================================
FILE: .wordpress-org/README.md
================================================
# WordPress.org assets
These assets are used in the WordPress.org plugin directory. They will need to be synced with the plugin SVN repository whenever they change.
================================================
FILE: .wordpress-org/blueprints/blueprint.json
================================================
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/plugins.php",
"preferredVersions": {
"php": "8.0",
"wp": "latest"
},
"phpExtensionBundles": ["kitchen-sink"],
"features": {
"networking": true
},
"steps": [
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "url",
"url": "https://downloads.wordpress.org/plugin/web-stories.latest-stable.zip"
},
"options": {
"activate": true
}
},
{
"step": "login",
"username": "admin",
"password": "password"
}
]
}
================================================
FILE: CONTRIBUTING.md
================================================
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Getting Started
Please check out our dedicated [Getting Started](./docs/getting-started.md) guide.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
## Community Guidelines
This project follows [Google's Open Source Community
Guidelines](https://opensource.google/conduct/).
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (o
Showing preview only (297K chars total). Download the full file or copy to clipboard to get everything.
gitextract_qcnlwv5k/ ├── .allstar/ │ └── branch_protection.yaml ├── .browserslistrc ├── .distignore ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .git-blame-ignore-revs ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yml │ │ ├── enhancement.md │ │ ├── epic.md │ │ └── task.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── SUPPORT.md │ ├── dependabot.yml │ ├── release.yml │ └── workflows/ │ ├── build-and-deploy.yml │ ├── codeql-analysis.yml │ ├── deploy-storybook.yml │ ├── lint-css-js-md.yml │ ├── lint-i18n.yml │ ├── lint-php.yml │ ├── lint-plugin-check.yml │ ├── npm-release.yml │ ├── plugin-release.yml │ ├── scorecards.yml │ ├── tests-e2e.yml │ ├── tests-karma-dashboard.yml │ ├── tests-karma-editor.yml │ ├── tests-unit-js.yml │ ├── tests-unit-php.yml │ ├── update-browserslist.yml │ ├── update-google-fonts.yml │ ├── update-product-schema.yml │ └── update-templates.yml ├── .gitignore ├── .husky/ │ └── pre-commit ├── .markdownlint.json ├── .markdownlintignore ├── .npmpackagejsonlintrc.json ├── .npmrc ├── .nvmrc ├── .oxlintrc.json ├── .phpstorm.config.js ├── .phpstorm.meta.php ├── .prettierignore ├── .prettierrc ├── .storybook/ │ ├── main.cjs │ ├── manager-head.html │ ├── preview-head.html │ ├── preview.js │ └── stories/ │ └── playground/ │ ├── dashboard/ │ │ ├── index.js │ │ └── theme.js │ └── story-editor/ │ ├── api/ │ │ ├── fonts.js │ │ ├── index.js │ │ ├── media.js │ │ └── story.js │ ├── constants.js │ ├── getDummyMedia.js │ ├── header/ │ │ ├── buttons/ │ │ │ ├── index.js │ │ │ ├── preview.js │ │ │ └── saveButton.js │ │ └── index.js │ ├── index.js │ └── preview.js ├── .stylelintignore ├── .stylelintrc ├── .wordpress-org/ │ ├── README.md │ └── blueprints/ │ └── blueprint.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── __mocks__/ │ ├── colorthief.js │ ├── node:fs.js │ └── react-moveable.js ├── __static__/ │ ├── README.md │ ├── asteroid.ogg │ ├── beach.webm │ └── ranger9.ogg ├── babel.config.cjs ├── bin/ │ ├── deploy-to-test-environment.sh │ ├── install-wp-tests.sh │ ├── local-env/ │ │ ├── docker-compose.yml │ │ ├── includes.sh │ │ ├── install-wordpress.sh │ │ ├── launch-containers.sh │ │ ├── start.sh │ │ ├── stop.sh │ │ └── uploads.ini │ ├── schemas/ │ │ └── story.json │ ├── setup-local-npm-registry.sh │ ├── stop-local-npm-registry.sh │ └── verdaccio-config.yml ├── blocks/ │ └── embed/ │ └── block.json ├── codecov.yml ├── composer.json ├── docs/ │ ├── README.md │ ├── accessibility-guidelines.md │ ├── accessibility-testing.md │ ├── animations.md │ ├── architecture.md │ ├── browser-support.md │ ├── canvas.md │ ├── cdn.md │ ├── checklist.md │ ├── code-style.md │ ├── design-docs.md │ ├── design-panel-push-update-flow.md │ ├── design-system.md │ ├── devtools.md │ ├── e2e-tests.md │ ├── environment-variables.md │ ├── external-template-creation.md │ ├── feature-flags.md │ ├── getting-started.md │ ├── glossary.md │ ├── integration-tests.md │ ├── local-environment.md │ ├── migrations.md │ ├── onboarding.md │ ├── page-templates.md │ ├── performance.md │ ├── quick-actions.md │ ├── right-click-menu.md │ ├── storybook.md │ ├── svgs.md │ ├── testing-environments.md │ ├── testing-qa.md │ ├── third-party-integration/ │ │ ├── dashboard/ │ │ │ ├── README.md │ │ │ ├── api-callbacks.md │ │ │ ├── getting-started.md │ │ │ ├── integration-layer.md │ │ │ └── tutorial.md │ │ └── story-editor/ │ │ ├── README.md │ │ ├── api-callbacks.md │ │ ├── getting-started.md │ │ ├── integration-layer.md │ │ └── tutorial.md │ ├── unit-tests.md │ ├── web-stories-embeds.md │ └── workflows.md ├── includes/ │ ├── AMP/ │ │ ├── Canonical_Sanitizer.php │ │ ├── Integration/ │ │ │ └── AMP_Story_Sanitizer.php │ │ ├── Meta_Sanitizer.php │ │ ├── Optimization.php │ │ ├── Output_Buffer.php │ │ ├── Sanitization.php │ │ ├── Story_Sanitizer.php │ │ ├── Tag_And_Attribute_Sanitizer.php │ │ └── Traits/ │ │ └── Sanitization_Utils.php │ ├── AMP_Story_Player_Assets.php │ ├── AdSense.php │ ├── Ad_Manager.php │ ├── Admin/ │ │ ├── Activation_Notice.php │ │ ├── Admin.php │ │ ├── Cross_Origin_Isolation.php │ │ ├── Customizer.php │ │ ├── Dashboard.php │ │ ├── Editor.php │ │ ├── Google_Fonts.php │ │ ├── Meta_Boxes.php │ │ ├── PluginActionLinks.php │ │ ├── PluginRowMeta.php │ │ ├── Site_Health.php │ │ └── TinyMCE.php │ ├── Analytics.php │ ├── Assets.php │ ├── Block/ │ │ └── Web_Stories_Block.php │ ├── Context.php │ ├── Database_Upgrader.php │ ├── Decoder.php │ ├── Demo_Content.php │ ├── Discovery.php │ ├── Embed_Base.php │ ├── Exception/ │ │ ├── FailedToMakeInstance.php │ │ ├── InvalidEventProperties.php │ │ ├── InvalidService.php │ │ ├── SanitizationException.php │ │ └── WebStoriesException.php │ ├── Experiments.php │ ├── Font_Post_Type.php │ ├── Infrastructure/ │ │ ├── Conditional.php │ │ ├── Delayed.php │ │ ├── HasMeta.php │ │ ├── HasRequirements.php │ │ ├── Injector/ │ │ │ ├── FallbackInstantiator.php │ │ │ ├── InjectionChain.php │ │ │ └── SimpleInjector.php │ │ ├── Injector.php │ │ ├── Instantiator.php │ │ ├── Plugin.php │ │ ├── PluginActivationAware.php │ │ ├── PluginDeactivationAware.php │ │ ├── PluginUninstallAware.php │ │ ├── Registerable.php │ │ ├── Service.php │ │ ├── ServiceBasedPlugin.php │ │ ├── ServiceContainer/ │ │ │ ├── LazilyInstantiatedService.php │ │ │ └── SimpleServiceContainer.php │ │ ├── ServiceContainer.php │ │ ├── SiteInitializationAware.php │ │ └── SiteRemovalAware.php │ ├── Integrations/ │ │ ├── AMP.php │ │ ├── Conditional_Featured_Image.php │ │ ├── Core_Themes_Support.php │ │ ├── Ezoic.php │ │ ├── Jetpack.php │ │ ├── New_Relic.php │ │ ├── NextGen_Gallery.php │ │ ├── Plugin_Status.php │ │ ├── ShortPixel.php │ │ ├── Site_Kit.php │ │ └── WooCommerce.php │ ├── Interfaces/ │ │ ├── Field.php │ │ ├── FieldState.php │ │ ├── FieldStateFactory.php │ │ ├── Migration.php │ │ ├── Product_Query.php │ │ └── Renderer.php │ ├── KSES.php │ ├── Locale.php │ ├── Media/ │ │ ├── Base_Color.php │ │ ├── Blurhash.php │ │ ├── Cropping.php │ │ ├── Image_Sizes.php │ │ ├── Media_Source_Taxonomy.php │ │ ├── SVG.php │ │ ├── Types.php │ │ └── Video/ │ │ ├── Captions.php │ │ ├── Is_Gif.php │ │ ├── Muting.php │ │ ├── Optimization.php │ │ ├── Poster.php │ │ └── Trimming.php │ ├── Mgid.php │ ├── Migrations/ │ │ ├── Add_Media_Source.php │ │ ├── Add_Media_Source_Editor.php │ │ ├── Add_Media_Source_Gif_Conversion.php │ │ ├── Add_Media_Source_Page_Template.php │ │ ├── Add_Media_Source_Recording.php │ │ ├── Add_Media_Source_Source_Image.php │ │ ├── Add_Media_Source_Source_Video.php │ │ ├── Add_Media_Source_Video_Optimization.php │ │ ├── Add_Poster_Generation_Media_Source.php │ │ ├── Add_Stories_Caps.php │ │ ├── Add_VideoPress_Poster_Generation_Media_Source.php │ │ ├── Migrate_Base.php │ │ ├── Migration_Meta_To_Term.php │ │ ├── Remove_Broken_Text_Styles.php │ │ ├── Remove_Incorrect_Tracking_Id.php │ │ ├── Remove_Unneeded_Attachment_Meta.php │ │ ├── Replace_Conic_Style_Presets.php │ │ ├── Rewrite_Flush.php │ │ ├── Set_Legacy_Analytics_Usage_Flag.php │ │ ├── Unify_Color_Presets.php │ │ ├── Update_1.php │ │ └── Update_Publisher_Logos.php │ ├── Model/ │ │ └── Story.php │ ├── Page_Template_Post_Type.php │ ├── Plugin.php │ ├── PluginFactory.php │ ├── Post_Type_Base.php │ ├── REST_API/ │ │ ├── Embed_Controller.php │ │ ├── Font_Controller.php │ │ ├── Hotlinking_Controller.php │ │ ├── Link_Controller.php │ │ ├── Page_Template_Controller.php │ │ ├── Products_Controller.php │ │ ├── Publisher_Logos_Controller.php │ │ ├── REST_Controller.php │ │ ├── Status_Check_Controller.php │ │ ├── Stories_Autosaves_Controller.php │ │ ├── Stories_Base_Controller.php │ │ ├── Stories_Controller.php │ │ ├── Stories_Lock_Controller.php │ │ ├── Stories_Media_Controller.php │ │ ├── Stories_Settings_Controller.php │ │ ├── Stories_Taxonomies_Controller.php │ │ ├── Stories_Terms_Controller.php │ │ └── Stories_Users_Controller.php │ ├── Register_Widget.php │ ├── Remove_Transients.php │ ├── Renderer/ │ │ ├── Archives.php │ │ ├── Feed.php │ │ ├── Oembed.php │ │ ├── Single.php │ │ ├── Stories/ │ │ │ ├── Carousel_Renderer.php │ │ │ ├── FieldState/ │ │ │ │ ├── BaseFieldState.php │ │ │ │ ├── CarouselView.php │ │ │ │ ├── CircleView.php │ │ │ │ ├── GridView.php │ │ │ │ └── ListView.php │ │ │ ├── FieldStateFactory/ │ │ │ │ └── Factory.php │ │ │ ├── Fields/ │ │ │ │ └── BaseField.php │ │ │ ├── Generic_Renderer.php │ │ │ └── Renderer.php │ │ └── Story/ │ │ ├── Embed.php │ │ ├── HTML.php │ │ ├── Image.php │ │ └── Singleton.php │ ├── Service_Base.php │ ├── Services.php │ ├── Settings.php │ ├── Shopping/ │ │ ├── Product.php │ │ ├── Product_Meta.php │ │ ├── Shopify_Query.php │ │ ├── Shopping_Vendors.php │ │ └── WooCommerce_Query.php │ ├── Shortcode/ │ │ ├── Embed_Shortcode.php │ │ └── Stories_Shortcode.php │ ├── Stories_Script_Data.php │ ├── Story_Archive.php │ ├── Story_Post_Type.php │ ├── Story_Query.php │ ├── Story_Revisions.php │ ├── Taxonomy/ │ │ ├── Category_Taxonomy.php │ │ ├── Tag_Taxonomy.php │ │ └── Taxonomy_Base.php │ ├── Tracking.php │ ├── User/ │ │ ├── Capabilities.php │ │ └── Preferences.php │ ├── Widgets/ │ │ └── Stories.php │ ├── compat/ │ │ ├── Web_Stories_Compatibility.php │ │ └── amp.php │ ├── data/ │ │ ├── fonts/ │ │ │ └── fonts.json │ │ └── stories/ │ │ └── demo.json │ ├── functions.php │ ├── namespace.php │ ├── polyfills/ │ │ └── mbstring.php │ └── templates/ │ ├── admin/ │ │ ├── activation-notice.php │ │ ├── dashboard.php │ │ ├── edit-story.php │ │ └── experiments.php │ └── frontend/ │ ├── embed-web-story.php │ └── single-web-story.php ├── jest-puppeteer.config.cjs ├── jsconfig.json ├── karma-dashboard.config.cjs ├── karma-story-editor.config.cjs ├── package.json ├── packages/ │ ├── activation-notice/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── components/ │ │ │ │ │ ├── dismiss.tsx │ │ │ │ │ ├── image.tsx │ │ │ │ │ ├── link.tsx │ │ │ │ │ ├── messageContent.tsx │ │ │ │ │ ├── number.tsx │ │ │ │ │ ├── paragraph.tsx │ │ │ │ │ ├── step1.tsx │ │ │ │ │ ├── step2.tsx │ │ │ │ │ ├── step3.tsx │ │ │ │ │ ├── successMessage.tsx │ │ │ │ │ └── test/ │ │ │ │ │ ├── dismiss.js │ │ │ │ │ ├── step1.js │ │ │ │ │ ├── step2.js │ │ │ │ │ ├── step3.js │ │ │ │ │ └── successMessage.js │ │ │ │ ├── config/ │ │ │ │ │ ├── configProvider.tsx │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useConfig.ts │ │ │ │ └── index.tsx │ │ │ ├── index.tsx │ │ │ ├── stories/ │ │ │ │ └── index.js │ │ │ ├── testUtils/ │ │ │ │ ├── index.js │ │ │ │ └── renderWithTheme.js │ │ │ ├── theme.ts │ │ │ └── typings/ │ │ │ └── styled-components.d.ts │ │ └── tsconfig.json │ ├── animation/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── components/ │ │ │ │ ├── AMPAnimations.tsx │ │ │ │ ├── AMPKeyframes.tsx │ │ │ │ ├── AMPWrapper.tsx │ │ │ │ ├── WAAPIWrapper.tsx │ │ │ │ ├── animationMachine.ts │ │ │ │ ├── context.ts │ │ │ │ ├── fullSizeAbsolute.ts │ │ │ │ ├── generateKeyframesMap.ts │ │ │ │ ├── index.ts │ │ │ │ ├── provider.tsx │ │ │ │ ├── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── test/ │ │ │ │ │ ├── WAAPIWrapper.tsx │ │ │ │ │ ├── animationProvider.tsx │ │ │ │ │ └── generateKeyframesMap.ts │ │ │ │ ├── types.ts │ │ │ │ └── useStoryAnimationContext.ts │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ ├── outputs/ │ │ │ │ ├── animationOutput.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── keyframesOutput.tsx │ │ │ │ ├── output.tsx │ │ │ │ └── types.ts │ │ │ ├── parts/ │ │ │ │ ├── createAnimation.tsx │ │ │ │ ├── createAnimationPart.ts │ │ │ │ ├── defaultFields.ts │ │ │ │ ├── effects/ │ │ │ │ │ ├── backgroundPan.ts │ │ │ │ │ ├── backgroundPanAndZoom.ts │ │ │ │ │ ├── backgroundZoom.ts │ │ │ │ │ ├── drop.ts │ │ │ │ │ ├── fadeIn.ts │ │ │ │ │ ├── flyIn.tsx │ │ │ │ │ ├── pan.ts │ │ │ │ │ ├── pulse.ts │ │ │ │ │ ├── rotateIn.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── drop.js │ │ │ │ │ │ ├── fadeIn.js │ │ │ │ │ │ ├── flyIn.js │ │ │ │ │ │ ├── pan.js │ │ │ │ │ │ ├── pulse.js │ │ │ │ │ │ ├── rotateIn.js │ │ │ │ │ │ ├── twirlIn.js │ │ │ │ │ │ ├── whooshIn.js │ │ │ │ │ │ └── zoom.js │ │ │ │ │ ├── twirlIn.tsx │ │ │ │ │ ├── whooshIn.tsx │ │ │ │ │ └── zoom.tsx │ │ │ │ ├── emptyAnimationPart.tsx │ │ │ │ ├── getAnimationEffectFields.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── simple/ │ │ │ │ │ ├── blinkOn.ts │ │ │ │ │ ├── bounce.ts │ │ │ │ │ ├── fade.ts │ │ │ │ │ ├── flip.ts │ │ │ │ │ ├── floatOn.ts │ │ │ │ │ ├── move.ts │ │ │ │ │ ├── pulse.ts │ │ │ │ │ ├── spin.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── blinkOn.js │ │ │ │ │ │ ├── bounce.js │ │ │ │ │ │ ├── fade.js │ │ │ │ │ │ ├── flip.js │ │ │ │ │ │ ├── floatOn.js │ │ │ │ │ │ ├── move.js │ │ │ │ │ │ ├── pulse.js │ │ │ │ │ │ ├── spin.js │ │ │ │ │ │ └── zoom.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── pulse.ts │ │ │ │ │ └── zoom.ts │ │ │ │ └── types.ts │ │ │ ├── storybookUtils/ │ │ │ │ ├── index.js │ │ │ │ └── utils/ │ │ │ │ └── ampBoilerplate.js │ │ │ ├── types/ │ │ │ │ ├── animation.ts │ │ │ │ ├── effects.ts │ │ │ │ ├── element.ts │ │ │ │ ├── index.ts │ │ │ │ ├── keyframes.ts │ │ │ │ ├── propTypes.ts │ │ │ │ └── storyAnimationState.ts │ │ │ ├── typings/ │ │ │ │ └── global.d.ts │ │ │ └── utils/ │ │ │ ├── createKeyframeEffect.ts │ │ │ ├── defaultUnit.ts │ │ │ ├── generateLookupMap.ts │ │ │ ├── getDefaultFieldValue.ts │ │ │ ├── getElementOffsets.ts │ │ │ ├── getGlobalSpace.ts │ │ │ ├── getInitialStyleFromKeyframes.ts │ │ │ ├── getOffPageOffset.ts │ │ │ ├── getTotalDuration.ts │ │ │ ├── index.ts │ │ │ ├── orderByKeys.ts │ │ │ ├── padArray.ts │ │ │ ├── sanitizeTimings.ts │ │ │ └── test/ │ │ │ ├── createKeyframeEffect.ts │ │ │ ├── defaultUnit.ts │ │ │ ├── generateLookupMap.ts │ │ │ ├── getElementOffsets.ts │ │ │ ├── getGlobalSpace.ts │ │ │ ├── getInitialStyleFromKeyframes.ts │ │ │ ├── getOffPageOffset.ts │ │ │ ├── getTotalDuration.ts │ │ │ ├── orderByKeys.ts │ │ │ ├── padArray.ts │ │ │ └── sanitizeTimings.ts │ │ └── tsconfig.json │ ├── commander/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── index.ts │ │ │ └── utils/ │ │ │ ├── appendRevisionToVersion.ts │ │ │ ├── bundlePlugin.ts │ │ │ ├── copyFiles.ts │ │ │ ├── createBuild.ts │ │ │ ├── deleteExistingZipFiles.ts │ │ │ ├── generateZipFile.ts │ │ │ ├── getCurrentVersionNumber.ts │ │ │ ├── getIgnoredFiles.ts │ │ │ ├── index.ts │ │ │ ├── resizeSvgPath.ts │ │ │ ├── test/ │ │ │ │ ├── appendRevisionToVersion.js │ │ │ │ ├── bundlePlugin.js │ │ │ │ ├── copyFiles.js │ │ │ │ ├── createBuild.js │ │ │ │ ├── deleteExistingZipFiles.js │ │ │ │ ├── generateZipFile.js │ │ │ │ ├── getCurrentVersionNumber.js │ │ │ │ ├── getIgnoredFiles.js │ │ │ │ ├── resizeSvgPaths.js │ │ │ │ ├── updateCdnUrl.js │ │ │ │ └── updateVersionNumbers.js │ │ │ ├── updateCdnUrl.ts │ │ │ └── updateVersionNumbers.ts │ │ └── tsconfig.json │ ├── dashboard/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── api/ │ │ │ │ │ ├── apiProvider.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── apiProvider.js │ │ │ │ │ ├── useApi.js │ │ │ │ │ ├── useApiAlerts.js │ │ │ │ │ ├── useStoryApi.js │ │ │ │ │ ├── useTaxonomyApi.js │ │ │ │ │ ├── useTemplateApi.js │ │ │ │ │ └── useUsersApi.js │ │ │ │ ├── config/ │ │ │ │ │ ├── configProvider.tsx │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useConfig.ts │ │ │ │ ├── index.js │ │ │ │ ├── reducer/ │ │ │ │ │ ├── story/ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── storyReducer.js │ │ │ │ │ ├── templates/ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── templateReducer.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── story.js │ │ │ │ │ └── templates.js │ │ │ │ ├── router/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── route.ts │ │ │ │ │ ├── routerProvider.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── route.js │ │ │ │ │ │ ├── router.js │ │ │ │ │ │ └── routerProvider.js │ │ │ │ │ └── useRouteHistory.ts │ │ │ │ ├── serializers/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── templates.js │ │ │ │ │ └── test/ │ │ │ │ │ └── templates.js │ │ │ │ ├── textContent/ │ │ │ │ │ └── index.js │ │ │ │ └── views/ │ │ │ │ ├── apiAlerts/ │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── constants.js │ │ │ │ ├── exploreTemplates/ │ │ │ │ │ ├── content/ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── templateGridItem.js │ │ │ │ │ │ ├── templateGridView.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── content.js │ │ │ │ │ ├── filters/ │ │ │ │ │ │ ├── TemplateFiltersProvider/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── templateFiltersProvider.js │ │ │ │ │ │ └── useTemplateFilters.js │ │ │ │ │ ├── header/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── header.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── exploreTemplates.karma.js │ │ │ │ │ ├── modal/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── templateDetails/ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ ├── content/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── header/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── header.js │ │ │ │ │ │ └── karma/ │ │ │ │ │ │ └── templateDetails.karma.js │ │ │ │ │ ├── templateFilters.js │ │ │ │ │ └── test/ │ │ │ │ │ └── templateFilters.js │ │ │ │ ├── filters/ │ │ │ │ │ ├── reducer.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── reducer.js │ │ │ │ │ └── types.js │ │ │ │ ├── index.js │ │ │ │ ├── myStories/ │ │ │ │ │ ├── content/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── listView/ │ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── storiesView/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── storyGridItem/ │ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── storyDisplayContent.js │ │ │ │ │ │ ├── storyGridView/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── storyListItem/ │ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ ├── content.js │ │ │ │ │ │ └── storiesView.js │ │ │ │ │ ├── filters/ │ │ │ │ │ │ ├── StoryFiltersProvider/ │ │ │ │ │ │ │ ├── author/ │ │ │ │ │ │ │ │ └── useAuthorFilter.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── taxonomy/ │ │ │ │ │ │ │ └── useTaxonomyFilters.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── storyFiltersProvider.js │ │ │ │ │ │ │ ├── useAuthorFilter.js │ │ │ │ │ │ │ └── useTaxonomyFilter.js │ │ │ │ │ │ └── useStoryFilters.js │ │ │ │ │ ├── header/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── storyStatusToggle.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── header.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── karma/ │ │ │ │ │ ├── myStories.karma.js │ │ │ │ │ └── myStoriesList.karma.js │ │ │ │ ├── shared/ │ │ │ │ │ ├── bodyViewOptions.js │ │ │ │ │ ├── emptyContentMessage.js │ │ │ │ │ ├── grid/ │ │ │ │ │ │ └── components.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── pageHeading.js │ │ │ │ │ ├── sortDropDown.js │ │ │ │ │ └── stories/ │ │ │ │ │ ├── emptyContentMessage.js │ │ │ │ │ └── pageHeading.js │ │ │ │ └── utils/ │ │ │ │ ├── composeTemplateFilter.js │ │ │ │ ├── getSearchOptions.js │ │ │ │ ├── getTemplateFilters.js │ │ │ │ ├── index.js │ │ │ │ └── test/ │ │ │ │ ├── composeTemplateFilter.js │ │ │ │ ├── getSearchOptions.js │ │ │ │ └── getTemplateFilters.js │ │ │ ├── components/ │ │ │ │ ├── cardGallery/ │ │ │ │ │ ├── components.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── cardGrid/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── card-grid.js │ │ │ │ ├── cardGridItem/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── cardGridItem.js │ │ │ │ ├── colorList/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── contentGutter/ │ │ │ │ │ └── index.js │ │ │ │ ├── dialog/ │ │ │ │ │ ├── dialog.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── fileUpload/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── fileUpload.js │ │ │ │ ├── index.js │ │ │ │ ├── inlineInputForm/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── inlineInputForm.js │ │ │ │ ├── interfaceSkeleton/ │ │ │ │ │ └── index.js │ │ │ │ ├── layout/ │ │ │ │ │ ├── fixed.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── provider.js │ │ │ │ │ ├── scrollable.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── useLayoutContext.js │ │ │ │ │ └── useLayoutContext.js │ │ │ │ ├── navProvider.js │ │ │ │ ├── pageStructure/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── leftRail.js │ │ │ │ │ ├── menuButton.js │ │ │ │ │ ├── navigationComponents.js │ │ │ │ │ ├── pageStructureComponents.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── menuButton.js │ │ │ │ │ └── test/ │ │ │ │ │ └── pageStructure.js │ │ │ │ ├── popoverMenu/ │ │ │ │ │ ├── story-menu-generator.js │ │ │ │ │ └── test/ │ │ │ │ │ └── story-menu-generator.js │ │ │ │ ├── scrollToTop/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── scrollToTop.js │ │ │ │ ├── storyMenu/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── storyMenu.js │ │ │ │ ├── table/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── table.js │ │ │ │ ├── tooltip/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── tooltip.js │ │ │ │ ├── types.js │ │ │ │ └── viewStyleBar/ │ │ │ │ ├── index.js │ │ │ │ ├── stories/ │ │ │ │ │ └── index.js │ │ │ │ └── test/ │ │ │ │ └── viewStyleBar.js │ │ │ ├── constants/ │ │ │ │ ├── components.ts │ │ │ │ ├── index.ts │ │ │ │ ├── pageStructure.ts │ │ │ │ ├── stories.ts │ │ │ │ └── templates.ts │ │ │ ├── dashboard.js │ │ │ ├── dataUtils/ │ │ │ │ ├── formattedStoriesArray.js │ │ │ │ ├── formattedTaxonomiesArray.js │ │ │ │ ├── formattedTaxonomyTermsObject.js │ │ │ │ ├── formattedTemplatesArray.js │ │ │ │ └── formattedUsersObject.js │ │ │ ├── getDefaultConfig.js │ │ │ ├── icons/ │ │ │ │ ├── index.ts │ │ │ │ └── stories/ │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── karma/ │ │ │ │ ├── apiProviderFixture.js │ │ │ │ ├── fixture.js │ │ │ │ └── integrationLayerTesting/ │ │ │ │ └── config.karma.js │ │ │ ├── propTypes.js │ │ │ ├── storybookUtils/ │ │ │ │ └── index.js │ │ │ ├── testUtils/ │ │ │ │ ├── groupTemplatesByTag.js │ │ │ │ ├── index.js │ │ │ │ ├── mockApiProvider.js │ │ │ │ └── renderWithProviders.js │ │ │ ├── theme.js │ │ │ ├── types/ │ │ │ │ ├── configProvider.ts │ │ │ │ ├── index.ts │ │ │ │ └── routerProvider.ts │ │ │ ├── typings/ │ │ │ │ └── svg.d.ts │ │ │ └── utils/ │ │ │ ├── groupBy.js │ │ │ ├── index.js │ │ │ ├── keyboardOnlyOutline.js │ │ │ ├── noop.js │ │ │ ├── test/ │ │ │ │ ├── groupBy.js │ │ │ │ ├── useDashboardResultsLabel.js │ │ │ │ ├── usePagePreviewSize.js │ │ │ │ ├── useStoryView.js │ │ │ │ └── useTemplateView.js │ │ │ ├── titleFormatted.js │ │ │ ├── useDashboardResultsLabel.js │ │ │ ├── usePagePreviewSize.js │ │ │ ├── useStoryView.js │ │ │ └── useTemplateView.js │ │ └── tsconfig.json │ ├── date/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── convertFormatString.ts │ │ │ ├── format.ts │ │ │ ├── formatDate.ts │ │ │ ├── formatDistance.ts │ │ │ ├── formatTime.ts │ │ │ ├── getOptions.ts │ │ │ ├── getRelativeDisplayDate.ts │ │ │ ├── getTimeZoneString.ts │ │ │ ├── hasLeadingZeros.ts │ │ │ ├── index.ts │ │ │ ├── is12Hour.ts │ │ │ ├── settings.ts │ │ │ ├── test/ │ │ │ │ ├── convertFormatString.ts │ │ │ │ ├── format.ts │ │ │ │ ├── formatDate.ts │ │ │ │ ├── formatTime.ts │ │ │ │ ├── getRelativeDisplayDate.ts │ │ │ │ ├── getTimeZoneString.ts │ │ │ │ ├── hasLeadingZeros.ts │ │ │ │ ├── is12Hour.ts │ │ │ │ └── toUTCDate.ts │ │ │ ├── third_party/ │ │ │ │ └── buildLocalizeFn.ts │ │ │ └── toUTCDate.ts │ │ └── tsconfig.json │ ├── design-system/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── components/ │ │ │ │ ├── banner/ │ │ │ │ │ ├── banner.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── button/ │ │ │ │ │ ├── button.tsx │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── button.js │ │ │ │ │ └── toggleButton.tsx │ │ │ │ ├── checkbox/ │ │ │ │ │ ├── checkbox.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── checkbox.js │ │ │ │ ├── chip/ │ │ │ │ │ ├── chip.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── index.js │ │ │ │ ├── circularProgress/ │ │ │ │ │ ├── circular.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── contextMenu/ │ │ │ │ │ ├── animationContainer.tsx │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── button.tsx │ │ │ │ │ │ ├── group.tsx │ │ │ │ │ │ ├── icon.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── item.tsx │ │ │ │ │ │ ├── label.ts │ │ │ │ │ │ ├── link.tsx │ │ │ │ │ │ ├── separator.tsx │ │ │ │ │ │ ├── shortcut.ts │ │ │ │ │ │ ├── styles.ts │ │ │ │ │ │ ├── subMenuTrigger.tsx │ │ │ │ │ │ └── suffix.ts │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── contextMenu.tsx │ │ │ │ │ ├── contextMenuProvider/ │ │ │ │ │ │ ├── context.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── provider.tsx │ │ │ │ │ │ └── useContextMenu.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── menu.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styled.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── contextMenu.js │ │ │ │ │ └── types.ts │ │ │ │ ├── datalist/ │ │ │ │ │ ├── container.tsx │ │ │ │ │ ├── datalist.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── list/ │ │ │ │ │ │ ├── defaultRenderer.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── list.tsx │ │ │ │ │ │ └── styled.ts │ │ │ │ │ ├── searchInput.tsx │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── dialog/ │ │ │ │ │ ├── dialog.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── dialog.js │ │ │ │ ├── disclosure/ │ │ │ │ │ ├── disclosure.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── dropDown/ │ │ │ │ │ ├── components.ts │ │ │ │ │ ├── dropdown.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── select/ │ │ │ │ │ │ ├── components.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── select.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── dropDown.js │ │ │ │ │ │ ├── select.js │ │ │ │ │ │ └── useDropDown.js │ │ │ │ │ ├── types.ts │ │ │ │ │ └── useDropDown.ts │ │ │ │ ├── hex/ │ │ │ │ │ ├── hex.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── index.ts │ │ │ │ ├── infiniteScroller/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── infiniteScroller.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── infiniteScroller.js │ │ │ │ ├── input/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── input.tsx │ │ │ │ │ ├── numericInput.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styled.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── input.js │ │ │ │ │ │ ├── useNumericInput.js │ │ │ │ │ │ └── validation.js │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── useNumericInput.tsx │ │ │ │ │ └── validation.ts │ │ │ │ ├── keyboard/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── gridview/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── getArrowDir.js │ │ │ │ │ │ │ ├── getColumn.js │ │ │ │ │ │ │ ├── getIndex.js │ │ │ │ │ │ │ └── getRow.js │ │ │ │ │ │ ├── useGridViewKeys.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── keyboard.tsx │ │ │ │ │ ├── keys.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── createShortcutAriaLabel.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── prettifyShortcut.js │ │ │ │ │ └── utils.ts │ │ │ │ ├── loadingBar/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loadingBar.tsx │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── loadingSpinner/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loadingSpinner.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── loadingSpinner.js │ │ │ │ ├── mediaInput/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── mediaInput.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── mediaInput.js │ │ │ │ │ └── types.ts │ │ │ │ ├── menu/ │ │ │ │ │ ├── components.ts │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── list/ │ │ │ │ │ │ ├── components.ts │ │ │ │ │ │ ├── defaultListItem.tsx │ │ │ │ │ │ ├── emptyList.tsx │ │ │ │ │ │ ├── groupLabel.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── list.tsx │ │ │ │ │ │ └── listGroup.tsx │ │ │ │ │ ├── menu.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── menu.js │ │ │ │ │ │ ├── useDropDownMenu.js │ │ │ │ │ │ └── utils.js │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── useDropDownMenu.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── modal/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── modal.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styles.ts │ │ │ │ │ └── test/ │ │ │ │ │ └── modal.js │ │ │ │ ├── notificationBubble/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── notificationBubble.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── types.ts │ │ │ │ ├── pill/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── pill.tsx │ │ │ │ │ ├── pillGroup.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── pill.js │ │ │ │ ├── popup/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── popup.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── popup.js │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── getOffset.ts │ │ │ │ │ ├── getTransforms.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── radio/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── radio.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── radio.js │ │ │ │ ├── search/ │ │ │ │ │ ├── components.ts │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── input/ │ │ │ │ │ │ ├── components.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── input.tsx │ │ │ │ │ ├── search.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── input.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── input.js │ │ │ │ │ │ ├── search.js │ │ │ │ │ │ └── useSearch.js │ │ │ │ │ ├── types.ts │ │ │ │ │ └── useSearch.ts │ │ │ │ ├── slider/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── slider.tsx │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── snackbar/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── snackbarContainer.tsx │ │ │ │ │ ├── snackbarMessage.tsx │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── snackbarContainer.js │ │ │ │ │ │ └── snackbarMessage.js │ │ │ │ │ └── types.ts │ │ │ │ ├── swatch/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── swatch.tsx │ │ │ │ ├── switch/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── switch.tsx │ │ │ │ │ └── test/ │ │ │ │ │ └── switch.js │ │ │ │ ├── textArea/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── textArea.js │ │ │ │ │ └── textArea.tsx │ │ │ │ ├── toggle/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── toggle.js │ │ │ │ │ └── toggle.tsx │ │ │ │ ├── tooltip/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── tail.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── tooltip.js │ │ │ │ │ └── tooltip.tsx │ │ │ │ ├── typography/ │ │ │ │ │ ├── display/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── headline/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── link/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── list/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styles.ts │ │ │ │ │ └── text/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ └── visuallyHidden.ts │ │ │ ├── contexts/ │ │ │ │ ├── index.ts │ │ │ │ ├── popup/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── popupProvider.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── usePopup.ts │ │ │ │ └── snackbar/ │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── snackbarProvider.tsx │ │ │ │ └── useSnackbar.ts │ │ │ ├── icons/ │ │ │ │ ├── index.ts │ │ │ │ └── stories/ │ │ │ │ └── index.js │ │ │ ├── images/ │ │ │ │ ├── index.ts │ │ │ │ └── stories/ │ │ │ │ └── index.js │ │ │ ├── index.ts │ │ │ ├── stories/ │ │ │ │ └── index.js │ │ │ ├── storybookUtils/ │ │ │ │ ├── darkThemeProvider.js │ │ │ │ ├── index.js │ │ │ │ └── sampleData.js │ │ │ ├── testUtils/ │ │ │ │ ├── index.js │ │ │ │ ├── queryById.js │ │ │ │ ├── renderWithProviders.js │ │ │ │ └── sampleData.js │ │ │ ├── theme/ │ │ │ │ ├── borders.ts │ │ │ │ ├── breakpoint.ts │ │ │ │ ├── colors.ts │ │ │ │ ├── constants/ │ │ │ │ │ ├── breakpoints.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── global/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.ts │ │ │ │ ├── helpers/ │ │ │ │ │ ├── centerContent.ts │ │ │ │ │ ├── expandPresetStyles.ts │ │ │ │ │ ├── fullSize.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── outline.ts │ │ │ │ │ ├── scrollbar.ts │ │ │ │ │ ├── transparentBg.ts │ │ │ │ │ └── visuallyHidden.ts │ │ │ │ ├── index.ts │ │ │ │ ├── stories/ │ │ │ │ │ ├── colors.js │ │ │ │ │ └── index.js │ │ │ │ ├── theme.ts │ │ │ │ ├── types.ts │ │ │ │ └── typography.ts │ │ │ ├── types/ │ │ │ │ ├── keyboard.ts │ │ │ │ ├── snackbar.ts │ │ │ │ ├── theme.ts │ │ │ │ └── typography.ts │ │ │ ├── typings/ │ │ │ │ ├── styled.d.ts │ │ │ │ └── svg.d.ts │ │ │ └── utils/ │ │ │ ├── constants.ts │ │ │ ├── deepMerge.ts │ │ │ ├── directions.ts │ │ │ ├── getKeyboardMovement.ts │ │ │ ├── index.ts │ │ │ ├── isNullOrUndefinedOrEmptyString.ts │ │ │ ├── labelAccessibilityValidator.ts │ │ │ ├── localStore.ts │ │ │ ├── noop.ts │ │ │ ├── panelSections.ts │ │ │ ├── panelTypes.ts │ │ │ ├── sessionStore.ts │ │ │ ├── test/ │ │ │ │ ├── deepMerge.js │ │ │ │ ├── labelAccessibilityValidator.js │ │ │ │ ├── uniqueEntriesByKey.js │ │ │ │ ├── useLiveRegion.js │ │ │ │ └── useMouseDownOutside.js │ │ │ ├── uniqueEntriesByKey.ts │ │ │ ├── useForwardedRef.ts │ │ │ ├── useLiveRegion.ts │ │ │ └── useMouseDownOutsideRef.ts │ │ └── tsconfig.json │ ├── dom/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── ensureFontLoaded.ts │ │ │ ├── escapeHTML.ts │ │ │ ├── index.ts │ │ │ ├── loadStylesheet.ts │ │ │ ├── stripHTML.ts │ │ │ └── test/ │ │ │ └── escapeHTML.ts │ │ └── tsconfig.json │ ├── e2e-test-utils/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── activatePlugin.js │ │ ├── activateRTL.js │ │ ├── addRequestInterception.js │ │ ├── addTextElement.js │ │ ├── checkVersion.js │ │ ├── config.js │ │ ├── createNewPost.js │ │ ├── createNewStory.js │ │ ├── createNewTerm.js │ │ ├── createURL.js │ │ ├── customFonts.js │ │ ├── deactivatePlugin.js │ │ ├── deactivateRTL.js │ │ ├── deleteAllMedia.js │ │ ├── deleteMedia.js │ │ ├── deleteWidgets.js │ │ ├── disableCheckbox.js │ │ ├── editStoryWithTitle.js │ │ ├── enableCheckbox.js │ │ ├── experimentalFeatures.js │ │ ├── getFileName.js │ │ ├── index.js │ │ ├── insertStoryTitle.js │ │ ├── insertWidget.js │ │ ├── isCurrentURL.js │ │ ├── loadPostEditor.js │ │ ├── loginUser.js │ │ ├── logoutUser.js │ │ ├── minWPVersionRequired.js │ │ ├── previewStory.js │ │ ├── publishPost.js │ │ ├── publishStory.js │ │ ├── setAnalyticsCode.js │ │ ├── shopping.js │ │ ├── takeSnapshot.js │ │ ├── toggleVideoOptimization.js │ │ ├── toolbarProfileOption.js │ │ ├── trashAllPosts.js │ │ ├── trashAllTerms.js │ │ ├── triggerHighPriorityChecklistSection.js │ │ ├── uploadFile.js │ │ ├── uploadMedia.js │ │ ├── uploadPublisherLogo.js │ │ ├── user.js │ │ ├── visitAdminPage.js │ │ ├── visitBlockWidgetScreen.js │ │ ├── visitDashboard.js │ │ ├── visitSettings.js │ │ ├── withPlugin.js │ │ ├── withRTL.js │ │ └── withUser.js │ ├── e2e-tests/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── assets/ │ │ │ ├── README.md │ │ │ ├── small-video.webm │ │ │ └── test.vtt │ │ ├── config/ │ │ │ └── bootstrap.js │ │ ├── jest.config.js │ │ ├── plugins/ │ │ │ ├── disable-block-directory.php │ │ │ ├── disable-gravatar.php │ │ │ ├── locked-post-mock.php │ │ │ ├── site-kit-adsense.php │ │ │ ├── site-kit-analytics.php │ │ │ ├── status-check-200-invalid.php │ │ │ ├── status-check-403.php │ │ │ ├── status-check-500.php │ │ │ ├── web-stories-cors-error.php │ │ │ ├── web-stories-disable-default-templates.php │ │ │ ├── web-stories-disable-media3p.php │ │ │ ├── web-stories-embed.php │ │ │ ├── web-stories-hotlink.php │ │ │ ├── web-stories-meta-box.php │ │ │ └── web-stories-taxonomies.php │ │ ├── puppeteerEnvironment.js │ │ ├── specs/ │ │ │ ├── dashboard/ │ │ │ │ ├── adminMenu.js │ │ │ │ ├── dashboard.js │ │ │ │ ├── documentTitle.js │ │ │ │ ├── myStories.js │ │ │ │ ├── noJS.js │ │ │ │ ├── settings/ │ │ │ │ │ ├── adminUser/ │ │ │ │ │ │ ├── analytics.js │ │ │ │ │ │ ├── customFonts.js │ │ │ │ │ │ ├── dataRemovalSettings.js │ │ │ │ │ │ ├── monetization.js │ │ │ │ │ │ ├── publisherLogo.js │ │ │ │ │ │ ├── shoppingProvider.js │ │ │ │ │ │ ├── telemetryBanner.js │ │ │ │ │ │ └── videoSettings.js │ │ │ │ │ ├── authorUser.js │ │ │ │ │ ├── contributorUser.js │ │ │ │ │ └── editorUser.js │ │ │ │ ├── telemetryBanner.js │ │ │ │ └── templates/ │ │ │ │ └── useTemplate.js │ │ │ ├── editor/ │ │ │ │ ├── authorUser.js │ │ │ │ ├── backgroundAudio.js │ │ │ │ ├── contributorUser.js │ │ │ │ ├── editor.js │ │ │ │ ├── floatingMenu.js │ │ │ │ ├── fontCheck.js │ │ │ │ ├── media/ │ │ │ │ │ ├── hotlinking.js │ │ │ │ │ ├── insert3PMedia.js │ │ │ │ │ ├── insertMediaFromDialog.js │ │ │ │ │ ├── insertMediaFromLibrary.js │ │ │ │ │ ├── insertMovVideo.js │ │ │ │ │ ├── insertWebMVideo.js │ │ │ │ │ └── svg.js │ │ │ │ ├── metaBoxes.js │ │ │ │ ├── noJS.js │ │ │ │ ├── pageTemplates.js │ │ │ │ ├── passwordProtected.js │ │ │ │ ├── pendingStories.js │ │ │ │ ├── prePublishChecklist/ │ │ │ │ │ ├── adminUser.js │ │ │ │ │ └── contributorUser.js │ │ │ │ ├── publishPanel/ │ │ │ │ │ └── adminUser.js │ │ │ │ ├── publishingFlow.js │ │ │ │ ├── saveStory.js │ │ │ │ ├── shopping/ │ │ │ │ │ ├── productMenu.js │ │ │ │ │ ├── schema.json │ │ │ │ │ └── woocommerce.js │ │ │ │ ├── sidebar.js │ │ │ │ ├── statusCheck.js │ │ │ │ ├── storyDetailsModal/ │ │ │ │ │ ├── adminUser.js │ │ │ │ │ └── contributorUser.js │ │ │ │ ├── taxonomy.js │ │ │ │ └── templates.js │ │ │ ├── integrations/ │ │ │ │ ├── amp.js │ │ │ │ └── sitekit.js │ │ │ └── wordpress/ │ │ │ ├── adminMenu.js │ │ │ ├── archive.js │ │ │ ├── blockWidget.js │ │ │ ├── corsCheck.js │ │ │ ├── getStartedStory.js │ │ │ ├── pluginActivation.js │ │ │ ├── postLocking.js │ │ │ ├── quickEdit.js │ │ │ ├── tinymce.js │ │ │ ├── webStoriesBlock.js │ │ │ └── widget.js │ │ └── utils/ │ │ ├── constants.js │ │ └── index.js │ ├── element-library/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── audioSticker/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.tsx │ │ │ │ ├── output.tsx │ │ │ │ └── test/ │ │ │ │ └── output.js │ │ │ ├── constants.ts │ │ │ ├── elementTypes.ts │ │ │ ├── gif/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── edit.tsx │ │ │ │ ├── frame.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── output.tsx │ │ │ │ └── test/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── output.js.snap │ │ │ │ └── output.js │ │ │ ├── image/ │ │ │ │ ├── constants.ts │ │ │ │ ├── edit.tsx │ │ │ │ ├── frame.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── output.tsx │ │ │ │ └── test/ │ │ │ │ └── output.js │ │ │ ├── index.ts │ │ │ ├── media/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── edit.tsx │ │ │ │ ├── editCropMoveable.tsx │ │ │ │ ├── editPanMoveable.tsx │ │ │ │ ├── frame.tsx │ │ │ │ ├── imageDisplay.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── output.tsx │ │ │ │ ├── scalePanel.tsx │ │ │ │ ├── textContent.ts │ │ │ │ ├── util.ts │ │ │ │ └── videoImage.tsx │ │ │ ├── product/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.tsx │ │ │ │ └── output.tsx │ │ │ ├── shape/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── output.tsx │ │ │ │ └── test/ │ │ │ │ └── output.js │ │ │ ├── shared/ │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── shared.ts │ │ │ │ ├── useCSSVarColorTransformHandler.ts │ │ │ │ ├── useColorTransformHandler.ts │ │ │ │ └── visibleImage.tsx │ │ │ ├── sticker/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.ts │ │ │ │ └── output.tsx │ │ │ ├── test/ │ │ │ │ └── index.js │ │ │ ├── text/ │ │ │ │ ├── constants.ts │ │ │ │ ├── display.tsx │ │ │ │ ├── edit.tsx │ │ │ │ ├── frame.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── output.tsx │ │ │ │ ├── outputWithUnits.tsx │ │ │ │ ├── test/ │ │ │ │ │ ├── output.js │ │ │ │ │ └── util.js │ │ │ │ ├── textContent.ts │ │ │ │ ├── updateForResizeEvent.ts │ │ │ │ └── util.ts │ │ │ ├── typings/ │ │ │ │ ├── global.d.ts │ │ │ │ ├── images.d.ts │ │ │ │ ├── styled.d.ts │ │ │ │ └── svg.d.ts │ │ │ ├── utils/ │ │ │ │ ├── noop.ts │ │ │ │ └── textMeasurements.tsx │ │ │ └── video/ │ │ │ ├── captions.tsx │ │ │ ├── constants.ts │ │ │ ├── controls.tsx │ │ │ ├── display.tsx │ │ │ ├── edit.tsx │ │ │ ├── frame.tsx │ │ │ ├── icon.tsx │ │ │ ├── index.ts │ │ │ ├── layer.ts │ │ │ ├── onDropHandler.ts │ │ │ ├── output.tsx │ │ │ ├── playPauseButton.tsx │ │ │ ├── test/ │ │ │ │ └── output.js │ │ │ └── trim.tsx │ │ └── tsconfig.json │ ├── elements/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── elementType.ts │ │ │ ├── index.ts │ │ │ ├── propTypes.ts │ │ │ ├── types/ │ │ │ │ ├── data.ts │ │ │ │ ├── element.ts │ │ │ │ ├── elementDefinition.ts │ │ │ │ ├── elementType.ts │ │ │ │ ├── index.ts │ │ │ │ ├── media.ts │ │ │ │ ├── page.ts │ │ │ │ ├── story.ts │ │ │ │ └── taxonomies.ts │ │ │ └── utils/ │ │ │ ├── createNewElement.ts │ │ │ ├── createPage.ts │ │ │ ├── duplicateElement.ts │ │ │ ├── duplicatePage.ts │ │ │ ├── elementIs.ts │ │ │ ├── getDefinitionForType.ts │ │ │ ├── getLayerName.ts │ │ │ ├── getOffsetCoordinates.ts │ │ │ ├── getTransformFlip.ts │ │ │ ├── index.ts │ │ │ └── isElementBelowLimit.ts │ │ └── tsconfig.json │ ├── eslint-import-resolver/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ └── index.cjs │ ├── fonts/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── scripts/ │ │ │ ├── cli.ts │ │ │ └── utils/ │ │ │ ├── buildFonts.ts │ │ │ ├── constants.ts │ │ │ ├── getFontFallback.ts │ │ │ ├── getFontMetrics.ts │ │ │ ├── normalizeFont.ts │ │ │ ├── test/ │ │ │ │ ├── buildFonts.js │ │ │ │ ├── getFontFallback.js │ │ │ │ ├── getFontMetrics.js │ │ │ │ └── normalizeFont.js │ │ │ └── types.ts │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── fonts.json │ │ │ ├── index.ts │ │ │ ├── test/ │ │ │ │ └── curatedFonts.ts │ │ │ ├── types.ts │ │ │ └── utils/ │ │ │ ├── getFontCSS.ts │ │ │ ├── getGoogleFontURL.ts │ │ │ ├── index.ts │ │ │ └── test/ │ │ │ ├── getFontCSS.js │ │ │ └── getGoogleFontURL.js │ │ └── tsconfig.json │ ├── glider/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── i18n/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── i18n.ts │ │ │ ├── index.ts │ │ │ ├── sprintf.ts │ │ │ ├── test/ │ │ │ │ ├── transformNode.tsx │ │ │ │ ├── translateToExclusiveList.ts │ │ │ │ ├── translateToInclusiveList.ts │ │ │ │ └── translateWithMarkup.tsx │ │ │ ├── transformNode.ts │ │ │ ├── translateToExclusiveList.ts │ │ │ ├── translateToInclusiveList.ts │ │ │ ├── translateWithMarkup.tsx │ │ │ └── types.ts │ │ └── tsconfig.json │ ├── jest-amp/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── index.js │ │ ├── toBeValidAMP.js │ │ ├── toBeValidAMPStoryElement.js │ │ ├── toBeValidAMPStoryPage.js │ │ └── utils.js │ ├── jest-puppeteer-amp/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── index.js │ │ └── toBeValidAMP.js │ ├── jest-resolver/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ └── index.cjs │ ├── karma-failed-tests-reporter/ │ │ ├── .eslintrc │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ └── index.cjs │ ├── karma-fixture/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── actPromise.js │ │ ├── client_with_context.html │ │ ├── componentStub.js │ │ ├── events.js │ │ ├── index.js │ │ └── init.js │ ├── karma-puppeteer-client/ │ │ ├── .eslintrc │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── client.js │ │ └── index.cjs │ ├── karma-puppeteer-launcher/ │ │ ├── .eslintrc │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── index.cjs │ │ ├── mouseWithDnd.cjs │ │ └── snapshot.cjs │ ├── masks/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── borderedMaskedElement.tsx │ │ │ ├── constants.ts │ │ │ ├── display.tsx │ │ │ ├── frame.tsx │ │ │ ├── index.ts │ │ │ ├── masks.ts │ │ │ ├── output.tsx │ │ │ ├── test/ │ │ │ │ ├── constants.js │ │ │ │ └── output.js │ │ │ ├── types.ts │ │ │ ├── typings/ │ │ │ │ └── styled-components.d.ts │ │ │ └── utils/ │ │ │ └── elementBorder.ts │ │ └── tsconfig.json │ ├── media/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── aspectRatiosApproximatelyMatch.ts │ │ │ ├── blob.ts │ │ │ ├── blobToFile.ts │ │ │ ├── calculateSrcSet.ts │ │ │ ├── createFileReader.ts │ │ │ ├── createResource.ts │ │ │ ├── fetchRemoteBlob.ts │ │ │ ├── fetchRemoteFile.ts │ │ │ ├── formatDuration.ts │ │ │ ├── formatMsToHMS.ts │ │ │ ├── getCanvasBlob.ts │ │ │ ├── getFileBasename.ts │ │ │ ├── getFileNameFromUrl.ts │ │ │ ├── getFirstFrameOfVideo.ts │ │ │ ├── getFocalFromOffset.ts │ │ │ ├── getImageDimensions.ts │ │ │ ├── getImageFromVideo.ts │ │ │ ├── getMediaSizePositionProps.ts │ │ │ ├── getMsFromHMS.ts │ │ │ ├── getResourceSize.ts │ │ │ ├── getSmallestUrlForWidth.ts │ │ │ ├── getTypeFromMime.ts │ │ │ ├── getVideoLength.ts │ │ │ ├── getVideoLengthDisplay.ts │ │ │ ├── hasVideoGotAudio.ts │ │ │ ├── index.ts │ │ │ ├── isAnimatedGif.ts │ │ │ ├── mimeTypes.ts │ │ │ ├── preloadImage.ts │ │ │ ├── preloadVideo.ts │ │ │ ├── preloadVideoMetadata.ts │ │ │ ├── readFile.ts │ │ │ ├── resourceIs.ts │ │ │ ├── resourceList.ts │ │ │ ├── seekVideo.ts │ │ │ ├── test/ │ │ │ │ ├── calculateSrcSet.ts │ │ │ │ ├── formatMsToHMS.ts │ │ │ │ ├── getFileBasename.ts │ │ │ │ ├── getMsFromHMS.ts │ │ │ │ ├── getResourceSize.ts │ │ │ │ ├── getSmallestUrlForWidth.ts │ │ │ │ ├── getVideoLengthDisplay.ts │ │ │ │ ├── isAnimatedGif.ts │ │ │ │ ├── mimeTypes.ts │ │ │ │ └── resourceList.ts │ │ │ ├── types/ │ │ │ │ ├── audioResource.ts │ │ │ │ ├── gifResource.ts │ │ │ │ ├── imageResource.ts │ │ │ │ ├── index.ts │ │ │ │ ├── mediaElement.ts │ │ │ │ ├── propTypes.ts │ │ │ │ ├── resource.ts │ │ │ │ ├── resourceCache.ts │ │ │ │ ├── resourceInput.ts │ │ │ │ ├── resourceType.ts │ │ │ │ ├── sequenceResource.ts │ │ │ │ └── videoResource.ts │ │ │ └── typings/ │ │ │ └── dom.d.ts │ │ └── tsconfig.json │ ├── migration/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── rollup.config.js │ │ ├── scripts/ │ │ │ ├── cli.js │ │ │ └── utils/ │ │ │ ├── test/ │ │ │ │ └── updateTemplates.js │ │ │ └── updateTemplates.js │ │ ├── src/ │ │ │ ├── index.ts │ │ │ ├── migrate.ts │ │ │ ├── migrations/ │ │ │ │ ├── test/ │ │ │ │ │ ├── v0001_storyDataArrayToObject.js │ │ │ │ │ ├── v0002_dataPixelTo1080.js │ │ │ │ │ ├── v0003_fullbleedToFill.js │ │ │ │ │ ├── v0004_mediaElementToResource.js │ │ │ │ │ ├── v0004_squareToShape.js │ │ │ │ │ ├── v0005_setOpacity.js │ │ │ │ │ ├── v0006_colorToPattern.js │ │ │ │ │ ├── v0007_setFlip.js │ │ │ │ │ ├── v0008_paddingToObject.js │ │ │ │ │ ├── v0009_defaultBackground.js │ │ │ │ │ ├── v0010_dataPixelTo440.js │ │ │ │ │ ├── v0011_pageAdvancement.js │ │ │ │ │ ├── v0012_setBackgroundTextMode.js │ │ │ │ │ ├── v0013_videoIdToId.js │ │ │ │ │ ├── v0014_oneTapLinkDeprecate.js │ │ │ │ │ ├── v0015_fontObjects.js │ │ │ │ │ ├── v0016_isFullbleedDeprecate.js │ │ │ │ │ ├── v0017_inlineTextProperties.js │ │ │ │ │ ├── v0018_defaultBackgroundElement.js │ │ │ │ │ ├── v0019_conicToLinear.js │ │ │ │ │ ├── v0020_isFillDeprecate.js │ │ │ │ │ ├── v0021_backgroundColorToPage.js │ │ │ │ │ ├── v0022_dataPixelTo412.js │ │ │ │ │ ├── v0023_convertOverlayPattern.js │ │ │ │ │ ├── v0024_blobsToSingleBlob.js │ │ │ │ │ ├── v0025_singleAnimationTarget.js │ │ │ │ │ ├── v0026_backgroundOverlayToOverlay.js │ │ │ │ │ ├── v0027_videoDuration.js │ │ │ │ │ ├── v0028_mark3pVideoAsOptimized.js │ │ │ │ │ ├── v0029_unifyGifResources.js │ │ │ │ │ ├── v0030_mark3pVideoAsMuted.js │ │ │ │ │ ├── v0031_normalizeResourceSizes.js │ │ │ │ │ ├── v0032_pageOutlinkTheme.js │ │ │ │ │ ├── v0033_removeTitleFromResource.js │ │ │ │ │ ├── v0034_removeUnusedBackgroundProps.js │ │ │ │ │ ├── v0035_markVideoAsExternal.js │ │ │ │ │ ├── v0036_changeBaseColorToHex.js │ │ │ │ │ ├── v0038_camelCaseResourceSizes.js │ │ │ │ │ ├── v0038_removeTransientMediaProperties.js │ │ │ │ │ ├── v0039_backgroundAudioFormatting.js │ │ │ │ │ ├── v0040_andadaFontToAndadaPro.js │ │ │ │ │ ├── v0041_removeFontProperties.js │ │ │ │ │ ├── v0042_removeTrackName.js │ │ │ │ │ ├── v0043_removeTagNames.js │ │ │ │ │ ├── v0044_unusedProperties.js │ │ │ │ │ ├── v0045_globalPageAdvancement.js │ │ │ │ │ ├── v0046_removeRedundantScalingProperties.js │ │ │ │ │ ├── v0047_fixBrokenTemplates.js │ │ │ │ │ └── v0048_removeBasedOnFromElements.js │ │ │ │ ├── v0001_storyDataArrayToObject.ts │ │ │ │ ├── v0002_dataPixelTo1080.ts │ │ │ │ ├── v0003_fullbleedToFill.ts │ │ │ │ ├── v0004_mediaElementToResource.ts │ │ │ │ ├── v0004_squareToShape.ts │ │ │ │ ├── v0005_setOpacity.ts │ │ │ │ ├── v0006_colorToPattern.ts │ │ │ │ ├── v0007_setFlip.ts │ │ │ │ ├── v0008_paddingToObject.ts │ │ │ │ ├── v0009_defaultBackground.ts │ │ │ │ ├── v0010_dataPixelTo440.ts │ │ │ │ ├── v0011_pageAdvancement.ts │ │ │ │ ├── v0012_setBackgroundTextMode.ts │ │ │ │ ├── v0013_videoIdToId.ts │ │ │ │ ├── v0014_oneTapLinkDeprecate.ts │ │ │ │ ├── v0015_fontObjects.ts │ │ │ │ ├── v0016_isFullbleedDeprecate.ts │ │ │ │ ├── v0017_inlineTextProperties.ts │ │ │ │ ├── v0018_defaultBackgroundElement.ts │ │ │ │ ├── v0019_conicToLinear.ts │ │ │ │ ├── v0020_isFillDeprecate.ts │ │ │ │ ├── v0021_backgroundColorToPage.ts │ │ │ │ ├── v0022_dataPixelTo412.ts │ │ │ │ ├── v0023_convertOverlayPattern.ts │ │ │ │ ├── v0024_blobsToSingleBlob.ts │ │ │ │ ├── v0025_singleAnimationTarget.ts │ │ │ │ ├── v0026_backgroundOverlayToOverlay.ts │ │ │ │ ├── v0027_videoDuration.ts │ │ │ │ ├── v0028_mark3pVideoAsOptimized.ts │ │ │ │ ├── v0029_unifyGifResources.ts │ │ │ │ ├── v0030_mark3pVideoAsMuted.ts │ │ │ │ ├── v0031_normalizeResourceSizes.ts │ │ │ │ ├── v0032_pageOutlinkTheme.ts │ │ │ │ ├── v0033_removeTitleFromResources.ts │ │ │ │ ├── v0034_removeUnusedBackgroundProps.ts │ │ │ │ ├── v0035_markVideoAsExternal.ts │ │ │ │ ├── v0036_changeBaseColorToHex.ts │ │ │ │ ├── v0037_removeTransientMediaProperties.ts │ │ │ │ ├── v0038_camelCaseResourceSizes.ts │ │ │ │ ├── v0039_backgroundAudioFormatting.ts │ │ │ │ ├── v0040_andadaFontToAndadaPro.ts │ │ │ │ ├── v0041_removeFontProperties.ts │ │ │ │ ├── v0042_removeTrackName.ts │ │ │ │ ├── v0043_removeTagNames.ts │ │ │ │ ├── v0044_unusedProperties.ts │ │ │ │ ├── v0045_globalPageAdvancement.ts │ │ │ │ ├── v0046_removeRedundantScalingProperties.ts │ │ │ │ ├── v0047_fixBrokenTemplates.ts │ │ │ │ └── v0048_removeBasedOnFromElements.ts │ │ │ └── types/ │ │ │ ├── element.ts │ │ │ ├── index.ts │ │ │ ├── pattern.ts │ │ │ ├── resource.ts │ │ │ └── story.ts │ │ └── tsconfig.json │ ├── moveable/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── areEventsDragging.ts │ │ │ ├── cropStyle.ts │ │ │ ├── index.ts │ │ │ ├── moveStyle.ts │ │ │ ├── moveable.tsx │ │ │ ├── overlay/ │ │ │ │ ├── context.ts │ │ │ │ ├── index.tsx │ │ │ │ └── withOverlay.tsx │ │ │ ├── test/ │ │ │ │ └── areEventsDragging.ts │ │ │ └── typings/ │ │ │ ├── styled-components.d.ts │ │ │ └── svg-imports.d.ts │ │ └── tsconfig.json │ ├── output/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── components/ │ │ │ │ └── withLink/ │ │ │ │ ├── index.tsx │ │ │ │ └── test/ │ │ │ │ └── output.tsx │ │ │ ├── constants.ts │ │ │ ├── element.tsx │ │ │ ├── index.ts │ │ │ ├── page.tsx │ │ │ ├── story.tsx │ │ │ ├── test/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ ├── page.tsx.snap │ │ │ │ │ └── textElement.tsx.snap │ │ │ │ ├── _utils/ │ │ │ │ │ └── constants.ts │ │ │ │ ├── page.tsx │ │ │ │ ├── story.tsx │ │ │ │ └── textElement.tsx │ │ │ ├── types.ts │ │ │ ├── typings/ │ │ │ │ ├── global.d.ts │ │ │ │ ├── jest.d.ts │ │ │ │ └── svg.d.ts │ │ │ └── utils/ │ │ │ ├── ampBoilerplate.tsx │ │ │ ├── backgroundAudio.tsx │ │ │ ├── fontDeclarations.tsx │ │ │ ├── getAutoAdvanceAfter.ts │ │ │ ├── getLongestMediaElement.ts │ │ │ ├── getPreloadResources.ts │ │ │ ├── getStoryMarkup.tsx │ │ │ ├── getTextElementTagNames.ts │ │ │ ├── getUsedAmpExtensions.ts │ │ │ ├── outlink.tsx │ │ │ ├── populateElementFontData.ts │ │ │ ├── shoppingAttachment.tsx │ │ │ ├── styles.tsx │ │ │ └── test/ │ │ │ ├── fontDeclarations.tsx │ │ │ ├── getAutoAdvanceAfter.ts │ │ │ ├── getLongestMediaElement.ts │ │ │ ├── getPreloadResources.ts │ │ │ ├── getStoryMarkup.ts │ │ │ ├── getTextElementTagNames.ts │ │ │ ├── getUsedAmpExtensions.ts │ │ │ └── populateElementFontData.ts │ │ └── tsconfig.json │ ├── patterns/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── convertToCSS.ts │ │ │ ├── createSolid.ts │ │ │ ├── createSolidFromString.ts │ │ │ ├── generatePatternStyles.ts │ │ │ ├── getColorFromGradientStyle.ts │ │ │ ├── getGradientStyleFromColor.ts │ │ │ ├── getHexFromSolid.ts │ │ │ ├── getHexFromSolidArray.ts │ │ │ ├── getHexFromValue.ts │ │ │ ├── getOpaquePattern.ts │ │ │ ├── getPreviewText.ts │ │ │ ├── getSolidFromHex.ts │ │ │ ├── hasGradient.ts │ │ │ ├── hasOpacity.ts │ │ │ ├── index.ts │ │ │ ├── isHexColorString.ts │ │ │ ├── isPatternEqual.ts │ │ │ ├── test/ │ │ │ │ ├── convertToCSS.ts │ │ │ │ ├── createSolid.ts │ │ │ │ ├── createSolidFromString.ts │ │ │ │ ├── generatePatternStyles.ts │ │ │ │ ├── getColorFromGradientStyle.ts │ │ │ │ ├── getHexFromValue.ts │ │ │ │ ├── getOpaquePattern.ts │ │ │ │ ├── getPreviewText.ts │ │ │ │ ├── getSolidFromHex.ts │ │ │ │ └── hasOpacity.ts │ │ │ └── types.ts │ │ └── tsconfig.json │ ├── react/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── context.ts │ │ │ ├── index.ts │ │ │ ├── react-dom.ts │ │ │ ├── react.ts │ │ │ ├── renderToStaticMarkup.ts │ │ │ ├── shallowEqual.ts │ │ │ ├── test/ │ │ │ │ ├── context.js │ │ │ │ └── useCombinedRefs.js │ │ │ ├── typings/ │ │ │ │ └── global.d.ts │ │ │ ├── useBatchingCallback.ts │ │ │ ├── useCombinedRefs.ts │ │ │ ├── useContextSelector.ts │ │ │ ├── useFocusOut.ts │ │ │ ├── useInitializedValue.ts │ │ │ ├── usePrevious.ts │ │ │ ├── useResizeEffect.ts │ │ │ ├── useUnmount.ts │ │ │ └── useWhyDidYouUpdate.ts │ │ └── tsconfig.json │ ├── rich-text/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── context.ts │ │ │ ├── customConstants.ts │ │ │ ├── customExport.ts │ │ │ ├── customImport.ts │ │ │ ├── customInlineDisplay.ts │ │ │ ├── draftUtils.ts │ │ │ ├── editor.tsx │ │ │ ├── fauxSelection.ts │ │ │ ├── formatters/ │ │ │ │ ├── color.ts │ │ │ │ ├── convert.ts │ │ │ │ ├── gradientColor.ts │ │ │ │ ├── index.ts │ │ │ │ ├── italic.ts │ │ │ │ ├── letterSpacing.ts │ │ │ │ ├── test/ │ │ │ │ │ ├── _utils.ts │ │ │ │ │ ├── color.tsx │ │ │ │ │ ├── italic.tsx │ │ │ │ │ ├── letterSpacing.tsx │ │ │ │ │ ├── underline.tsx │ │ │ │ │ ├── uppercase.tsx │ │ │ │ │ └── weight.tsx │ │ │ │ ├── underline.ts │ │ │ │ ├── uppercase.ts │ │ │ │ ├── util.ts │ │ │ │ └── weight.ts │ │ │ ├── getFontVariants.ts │ │ │ ├── getPastedBlocks.ts │ │ │ ├── getStateInfo.ts │ │ │ ├── getTextColors.ts │ │ │ ├── htmlManipulation.ts │ │ │ ├── index.ts │ │ │ ├── provider.tsx │ │ │ ├── styleManipulation.ts │ │ │ ├── test/ │ │ │ │ ├── getFontVariants.ts │ │ │ │ ├── getPastedBlocks.ts │ │ │ │ ├── getTextColors.ts │ │ │ │ └── styleManipulation.ts │ │ │ ├── types.ts │ │ │ ├── typings/ │ │ │ │ └── jest.d.ts │ │ │ ├── useHandlePastedText.ts │ │ │ ├── usePasteTextContent.ts │ │ │ ├── useRichText.ts │ │ │ ├── useSelectionManipulation.ts │ │ │ ├── util.ts │ │ │ └── utils/ │ │ │ ├── getCaretCharacterOffsetWithin.ts │ │ │ └── getValidHTML.ts │ │ └── tsconfig.json │ ├── stickers/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── 12-hours-in-barcelona/ │ │ │ │ ├── index.ts │ │ │ │ ├── list.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ └── yellowLocationPin.tsx │ │ │ ├── a-day-in-the-life/ │ │ │ │ ├── alarmClock.tsx │ │ │ │ ├── brownRice.tsx │ │ │ │ ├── dumbbells.tsx │ │ │ │ ├── fish.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── jumpRope.tsx │ │ │ │ ├── whiteBag.tsx │ │ │ │ └── yellowLeaves.tsx │ │ │ ├── ace-hotel-kyoto-review/ │ │ │ │ ├── greenCup.tsx │ │ │ │ ├── greenCutlery.tsx │ │ │ │ ├── greenHandBag.tsx │ │ │ │ └── index.ts │ │ │ ├── all-about-cars/ │ │ │ │ ├── blueRings.tsx │ │ │ │ ├── index.ts │ │ │ │ └── multipleBlueRings.tsx │ │ │ ├── almodos-films/ │ │ │ │ ├── heptagram.tsx │ │ │ │ └── index.ts │ │ │ ├── an-artists-legacy/ │ │ │ │ ├── brushStroke.tsx │ │ │ │ └── index.ts │ │ │ ├── art-books-gift-guide/ │ │ │ │ ├── books.tsx │ │ │ │ ├── handHeldSign.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── manReading.tsx │ │ │ │ ├── openHands.tsx │ │ │ │ ├── photoFrame.tsx │ │ │ │ ├── womanReading.tsx │ │ │ │ └── womanReading02.tsx │ │ │ ├── baking-bread-guide/ │ │ │ │ ├── breadBun.tsx │ │ │ │ ├── dough.tsx │ │ │ │ ├── flourBag.tsx │ │ │ │ ├── flourBowl.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── jar.tsx │ │ │ │ ├── thermometer.tsx │ │ │ │ └── yeastPackage.tsx │ │ │ ├── beauty-quiz/ │ │ │ │ ├── greenBlob.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── pinkBlob.tsx │ │ │ │ └── tiltedGreenBlob.tsx │ │ │ ├── belly-fat-workout/ │ │ │ │ ├── blackSectionSeparator.tsx │ │ │ │ └── index.ts │ │ │ ├── buying-art-on-the-internet/ │ │ │ │ ├── blackInstagram.tsx │ │ │ │ └── index.ts │ │ │ ├── celebrity-life-story/ │ │ │ │ ├── blackStar.tsx │ │ │ │ ├── greenStar.tsx │ │ │ │ └── index.ts │ │ │ ├── diy-home-office/ │ │ │ │ ├── index.ts │ │ │ │ └── offWhiteArrow.tsx │ │ │ ├── doers-get-more-done/ │ │ │ │ ├── facebookIcon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── instagramIcon.tsx │ │ │ │ ├── orangeCross.tsx │ │ │ │ ├── orangeDot.tsx │ │ │ │ ├── plus.tsx │ │ │ │ ├── rightArrow.tsx │ │ │ │ ├── twitterIcon.tsx │ │ │ │ └── youTubeIcon.tsx │ │ │ ├── elegant-travel-itinerary/ │ │ │ │ ├── floralFrame.tsx │ │ │ │ ├── floralSeparator.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── stationClock.tsx │ │ │ │ ├── trainTracks.tsx │ │ │ │ └── yellowBridge.tsx │ │ │ ├── experience-thailand/ │ │ │ │ ├── facebookIcon.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── instagramIcon.tsx │ │ │ │ ├── mapFill.tsx │ │ │ │ ├── twitterIcon.tsx │ │ │ │ └── youTubeIcon.tsx │ │ │ ├── fashion-inspiration/ │ │ │ │ ├── curvedArrow.tsx │ │ │ │ ├── cutout.tsx │ │ │ │ └── index.ts │ │ │ ├── fashion-on-the-go/ │ │ │ │ ├── arrowDark.tsx │ │ │ │ ├── arrowLight.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── starburst.tsx │ │ │ │ ├── starburstSolid.tsx │ │ │ │ └── starburstWithArrow.tsx │ │ │ ├── fitness-apps-ranked/ │ │ │ │ ├── dumbbells.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── muscle.tsx │ │ │ │ ├── piechart.tsx │ │ │ │ ├── running.tsx │ │ │ │ ├── shoe.tsx │ │ │ │ └── swimmer.tsx │ │ │ ├── food-and-stuff/ │ │ │ │ ├── arrow.tsx │ │ │ │ ├── artichoke.tsx │ │ │ │ ├── carrot.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── persimmon.tsx │ │ │ │ ├── radish.tsx │ │ │ │ └── radishLarge.tsx │ │ │ ├── fresh-and-bright/ │ │ │ │ ├── cta.tsx │ │ │ │ ├── heart.tsx │ │ │ │ └── index.ts │ │ │ ├── hawaii-travel-packing-list/ │ │ │ │ ├── cartBag.tsx │ │ │ │ ├── greenLeaf.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── palmLeaf.tsx │ │ │ │ └── palmTree.tsx │ │ │ ├── honeymooning-in-italy/ │ │ │ │ ├── floralPattern.tsx │ │ │ │ └── index.ts │ │ │ ├── how-contact-tracing-works/ │ │ │ │ ├── index.ts │ │ │ │ ├── phoneInHand.tsx │ │ │ │ └── rings.tsx │ │ │ ├── how-video-calls-saved-the-day/ │ │ │ │ ├── chatBox.tsx │ │ │ │ ├── index.ts │ │ │ │ └── yellowBrowser.tsx │ │ │ ├── index.ts │ │ │ ├── indoor-garden-oasis/ │ │ │ │ ├── curvedScissor.tsx │ │ │ │ ├── floral.tsx │ │ │ │ ├── greenBag.tsx │ │ │ │ ├── greenBulb.tsx │ │ │ │ ├── greenCurvedLine.tsx │ │ │ │ ├── greenLightning.tsx │ │ │ │ ├── greenSun.tsx │ │ │ │ ├── greenSunLight.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── lengthComparison.tsx │ │ │ │ ├── lightYellowArrow.tsx │ │ │ │ ├── scissor.tsx │ │ │ │ └── waterDroplet.tsx │ │ │ ├── kitchen-stories/ │ │ │ │ ├── castIron.tsx │ │ │ │ ├── hotDish.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── oven.tsx │ │ │ │ └── potatoes.tsx │ │ │ ├── laptop-buying-guide/ │ │ │ │ ├── index.ts │ │ │ │ ├── laptopFull.tsx │ │ │ │ ├── laptopHalf.tsx │ │ │ │ ├── laptopOff.tsx │ │ │ │ └── laptopThreeFourth.tsx │ │ │ ├── los-angeles-city-guide/ │ │ │ │ ├── greenLocationPin.tsx │ │ │ │ └── index.ts │ │ │ ├── magazine-article/ │ │ │ │ ├── flightPath.tsx │ │ │ │ └── index.ts │ │ │ ├── modernist-travel-guide/ │ │ │ │ ├── index.ts │ │ │ │ └── linedCircle.tsx │ │ │ ├── new-york-party-round-up/ │ │ │ │ ├── index.ts │ │ │ │ ├── instagramIcon.tsx │ │ │ │ ├── partyCircleText.tsx │ │ │ │ ├── twitchIcon.tsx │ │ │ │ └── twitterIcon.tsx │ │ │ ├── no-days-off/ │ │ │ │ ├── cta.tsx │ │ │ │ └── index.ts │ │ │ ├── one-day-city-itinerary/ │ │ │ │ ├── creamSectionSeparator.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── offWhiteLocation.tsx │ │ │ │ ├── redSectionSeparator.tsx │ │ │ │ └── whiteLine.tsx │ │ │ ├── pizzas-in-nyc/ │ │ │ │ ├── arrowRight.tsx │ │ │ │ ├── cheese.tsx │ │ │ │ ├── chili.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── mediumBrushStroke.tsx │ │ │ │ ├── onion.tsx │ │ │ │ ├── thickBrushStroke.tsx │ │ │ │ ├── tiltedBrushStroke.tsx │ │ │ │ ├── tomatoes.tsx │ │ │ │ └── veggies.tsx │ │ │ ├── plant-based-dyes/ │ │ │ │ ├── bannerWithDots.tsx │ │ │ │ ├── greenLeaf.tsx │ │ │ │ ├── greenLeafShape.tsx │ │ │ │ ├── greenRoundBanner.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── offWhiteBanner.tsx │ │ │ │ ├── offWhiteSectionSeparator.tsx │ │ │ │ ├── plant.tsx │ │ │ │ ├── roundedBannerWithDots.tsx │ │ │ │ ├── squigglyLine.tsx │ │ │ │ ├── wavyLine.tsx │ │ │ │ ├── yellowDots.tsx │ │ │ │ ├── yellowLeaf.tsx │ │ │ │ └── yellowRoundBanner.tsx │ │ │ ├── rock-music-festival/ │ │ │ │ ├── flames.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── orangeLightning.tsx │ │ │ │ └── whiteLightning.tsx │ │ │ ├── sangria-artichoke/ │ │ │ │ ├── curvedArrow.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── openPill.tsx │ │ │ │ ├── pillBox.tsx │ │ │ │ ├── pills.tsx │ │ │ │ ├── scribbledArrow.tsx │ │ │ │ ├── scribbledUnderline.tsx │ │ │ │ ├── scribbledUnderline2.tsx │ │ │ │ └── scribbledUnderlineWhite.tsx │ │ │ ├── skin-care-at-home/ │ │ │ │ ├── combAndScissors.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── palmIcon.tsx │ │ │ │ ├── sleepMask.tsx │ │ │ │ ├── toiletries.tsx │ │ │ │ ├── towelTurban.tsx │ │ │ │ └── violetLotus.tsx │ │ │ ├── sleep/ │ │ │ │ ├── arrowDark.tsx │ │ │ │ ├── arrowLight.tsx │ │ │ │ ├── cta.tsx │ │ │ │ └── index.ts │ │ │ ├── street-style-on-the-go/ │ │ │ │ ├── index.ts │ │ │ │ └── tap.tsx │ │ │ ├── summer-adventure-guide/ │ │ │ │ ├── dashedTrail.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── plus.tsx │ │ │ │ ├── share.tsx │ │ │ │ └── terrainMap.tsx │ │ │ ├── summer-fashion-collection/ │ │ │ │ ├── index.ts │ │ │ │ ├── yellowHeart.tsx │ │ │ │ ├── yellowInstagram.tsx │ │ │ │ └── yellowStar.tsx │ │ │ ├── sustainability-tips/ │ │ │ │ ├── cloudBanner.tsx │ │ │ │ └── index.ts │ │ │ ├── technology-advice/ │ │ │ │ ├── grayFrameCorner.tsx │ │ │ │ ├── index.ts │ │ │ │ └── whiteFrameCorner.tsx │ │ │ ├── tips-for-throwing-an-outdoor-luau/ │ │ │ │ ├── greenFlower.tsx │ │ │ │ ├── greenLeafBanner.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── whiteDottedArrow.tsx │ │ │ │ ├── yellowFlower.tsx │ │ │ │ ├── yellowFlowerBanner.tsx │ │ │ │ └── yellowWavyLine.tsx │ │ │ ├── tv-show-recap/ │ │ │ │ ├── curvedDottedLine.tsx │ │ │ │ ├── discPieChart.tsx │ │ │ │ ├── dottedDiamond.tsx │ │ │ │ └── index.ts │ │ │ ├── types.ts │ │ │ ├── vintage-chairs-what-to-look-for/ │ │ │ │ ├── chair.tsx │ │ │ │ ├── chair02.tsx │ │ │ │ └── index.ts │ │ │ └── weekly-entertainment/ │ │ │ ├── entertainmentStar.tsx │ │ │ ├── index.ts │ │ │ └── musicNote.tsx │ │ └── tsconfig.json │ ├── stories-block/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── block/ │ │ │ │ ├── block-types/ │ │ │ │ │ ├── latest-stories/ │ │ │ │ │ │ └── edit.js │ │ │ │ │ ├── selected-stories/ │ │ │ │ │ │ ├── edit.js │ │ │ │ │ │ └── embedPlaceholder.js │ │ │ │ │ └── single-story/ │ │ │ │ │ ├── edit.css │ │ │ │ │ ├── edit.js │ │ │ │ │ ├── editInLoop.js │ │ │ │ │ ├── embedControls.js │ │ │ │ │ ├── embedControlsInLoop.js │ │ │ │ │ ├── embedLoading.js │ │ │ │ │ ├── embedPlaceholder.js │ │ │ │ │ ├── embedPreview.js │ │ │ │ │ ├── insertFromURLPopover.js │ │ │ │ │ ├── singleton.js │ │ │ │ │ ├── storyPlayer.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── embedLoading.js │ │ │ │ │ ├── embedPlaceholder.js │ │ │ │ │ ├── embedPreview.js │ │ │ │ │ └── storyPlayer.js │ │ │ │ ├── block.js │ │ │ │ ├── components/ │ │ │ │ │ ├── authorSelection.js │ │ │ │ │ ├── autocomplete.js │ │ │ │ │ ├── blockTypeSwitcher.js │ │ │ │ │ ├── loaderContainer.js │ │ │ │ │ ├── storiesBlockConfigurationPanel.js │ │ │ │ │ ├── storiesBlockControls.js │ │ │ │ │ ├── storiesInspectorControls.js │ │ │ │ │ ├── storiesLoading.js │ │ │ │ │ ├── storiesPreview.js │ │ │ │ │ ├── storyCard.js │ │ │ │ │ ├── storyPicker/ │ │ │ │ │ │ ├── fetchSelectedStories.js │ │ │ │ │ │ ├── itemOverlay.js │ │ │ │ │ │ ├── selectStories.js │ │ │ │ │ │ ├── sortStories.js │ │ │ │ │ │ ├── storyPicker.js │ │ │ │ │ │ └── storyPreview.js │ │ │ │ │ ├── taxonomyItem.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── blockTypeSwitcher.js │ │ │ │ │ ├── loaderContainer.js │ │ │ │ │ └── storyCard.js │ │ │ │ ├── constants.js │ │ │ │ ├── deprecated.js │ │ │ │ ├── edit.css │ │ │ │ ├── edit.js │ │ │ │ ├── icons.js │ │ │ │ ├── index.js │ │ │ │ ├── save.js │ │ │ │ ├── test/ │ │ │ │ │ ├── autocomplete.js │ │ │ │ │ ├── block.js │ │ │ │ │ ├── save.js │ │ │ │ │ └── storiesPlaceholder.js │ │ │ │ └── transforms.js │ │ │ ├── css/ │ │ │ │ ├── common.css │ │ │ │ ├── core-themes/ │ │ │ │ │ ├── twentyeleven.css │ │ │ │ │ ├── twentyfifteen.css │ │ │ │ │ ├── twentyfourteen.css │ │ │ │ │ ├── twentyseventeen.css │ │ │ │ │ ├── twentysixteen.css │ │ │ │ │ ├── twentyten.css │ │ │ │ │ ├── twentytwelve.css │ │ │ │ │ ├── twentytwenty.css │ │ │ │ │ └── twentytwentyone.css │ │ │ │ ├── embed.css │ │ │ │ ├── lightbox.css │ │ │ │ ├── singleton.css │ │ │ │ ├── style.css │ │ │ │ ├── variables.css │ │ │ │ └── views/ │ │ │ │ ├── carousel.css │ │ │ │ ├── circles.css │ │ │ │ ├── grid.css │ │ │ │ └── list.css │ │ │ ├── index.js │ │ │ ├── publicPath.js │ │ │ └── view.ts │ │ └── tsconfig.json │ ├── stories-carousel/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── @types/ │ │ │ │ └── global.d.ts │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── story-editor/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── api/ │ │ │ │ │ ├── apiProvider.tsx │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ └── apiProvider.js │ │ │ │ │ └── useAPI.ts │ │ │ │ ├── canvas/ │ │ │ │ │ ├── canvasProvider.tsx │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── useAddPastedElements.ts │ │ │ │ │ ├── useCanvas.ts │ │ │ │ │ ├── useCanvasBoundingBox.ts │ │ │ │ │ ├── useCanvasCopyPaste.ts │ │ │ │ │ ├── useCanvasKeys.ts │ │ │ │ │ ├── useEditingElement.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── getLayerArrangementProps.ts │ │ │ │ │ └── test/ │ │ │ │ │ └── getLayerArrangementProps.js │ │ │ │ ├── config/ │ │ │ │ │ ├── configProvider.tsx │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useConfig.ts │ │ │ │ ├── currentUser/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── currentUserProvider.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useCurrentUser.ts │ │ │ │ ├── font/ │ │ │ │ │ ├── actions/ │ │ │ │ │ │ └── useLoadFontFiles.ts │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── fontProvider.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── actions/ │ │ │ │ │ │ └── useLoadFontFiles.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── useFont.ts │ │ │ │ ├── helpCenter/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── provider.tsx │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── useHelpCenter/ │ │ │ │ │ │ ├── effects.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── test/ │ │ │ │ │ │ ├── effects.ts │ │ │ │ │ │ └── useHelpCenter.tsx │ │ │ │ │ └── useHelpCenterReducer.ts │ │ │ │ ├── highlights/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── provider.tsx │ │ │ │ │ ├── states.ts │ │ │ │ │ ├── styles.js │ │ │ │ │ └── useHighlights.ts │ │ │ │ ├── history/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── historyProvider.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── history.karma.js │ │ │ │ │ ├── reducer.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── reducer.js │ │ │ │ │ ├── useHistory.ts │ │ │ │ │ └── useHistoryReducer.ts │ │ │ │ ├── index.js │ │ │ │ ├── layout/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── layoutProvider.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── useZoomSetting.js │ │ │ │ │ ├── useCarouselDrawer.ts │ │ │ │ │ ├── useLayout.ts │ │ │ │ │ └── useZoomSetting.ts │ │ │ │ ├── media/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── local/ │ │ │ │ │ │ ├── actions.js │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ ├── reducers/ │ │ │ │ │ │ │ ├── addAudioProcessing.js │ │ │ │ │ │ │ ├── addPosterProcessing.js │ │ │ │ │ │ │ ├── fetchMedia.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── prependMedia.js │ │ │ │ │ │ │ ├── removeAudioProcessing.js │ │ │ │ │ │ │ ├── removePosterProcessing.js │ │ │ │ │ │ │ ├── resetFilters.js │ │ │ │ │ │ │ ├── setMedia.js │ │ │ │ │ │ │ ├── setMediaType.js │ │ │ │ │ │ │ ├── setSearchTerm.js │ │ │ │ │ │ │ └── setupState.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ │ ├── useContextValueProvider.js │ │ │ │ │ │ │ └── useLocalMedia.js │ │ │ │ │ │ ├── typedefs.js │ │ │ │ │ │ ├── types.js │ │ │ │ │ │ ├── useContextValueProvider.js │ │ │ │ │ │ └── useLocalMedia.js │ │ │ │ │ ├── media3p/ │ │ │ │ │ │ ├── actions.js │ │ │ │ │ │ ├── api/ │ │ │ │ │ │ │ ├── apiFetcher.js │ │ │ │ │ │ │ ├── context.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── media3pApiProvider.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── apiFetcher.js │ │ │ │ │ │ │ │ └── useMedia3pApi.js │ │ │ │ │ │ │ ├── typedefs.js │ │ │ │ │ │ │ └── useMedia3pApi.js │ │ │ │ │ │ ├── attribution.js │ │ │ │ │ │ ├── categories/ │ │ │ │ │ │ │ ├── actions.js │ │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── reducer.js │ │ │ │ │ │ │ ├── typedefs.js │ │ │ │ │ │ │ └── types.js │ │ │ │ │ │ ├── providerConfiguration.js │ │ │ │ │ │ ├── providerReducer.js │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── providerReducer.js │ │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ │ ├── useContextValueProvider.js │ │ │ │ │ │ │ ├── useFetchCategoriesEffect.js │ │ │ │ │ │ │ └── useFetchMediaEffect.js │ │ │ │ │ │ ├── typedefs.js │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ ├── useContextValueProvider.js │ │ │ │ │ │ ├── useFetchCategoriesEffect.js │ │ │ │ │ │ ├── useFetchMediaEffect.js │ │ │ │ │ │ └── useProviderContextValueProvider.js │ │ │ │ │ ├── mediaProvider.js │ │ │ │ │ ├── pagination/ │ │ │ │ │ │ ├── actions.js │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── reducer.js │ │ │ │ │ │ └── types.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── useMediaReducer.js │ │ │ │ │ │ └── useUploadMedia.js │ │ │ │ │ ├── typedefs.js │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── uploadQueue/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── reducer.ts │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ │ └── useMediaUploadQueue.js │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ ├── useMediaUploadQueue.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── useMedia.js │ │ │ │ │ ├── useMediaReducer.js │ │ │ │ │ ├── useUploadMedia.js │ │ │ │ │ └── utils/ │ │ │ │ │ ├── getPosterName.ts │ │ │ │ │ ├── getResourceFromLocalFile.ts │ │ │ │ │ ├── getResourceFromMedia3p.js │ │ │ │ │ ├── getResourceFromUrl.ts │ │ │ │ │ ├── heif/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── useConvertHeif.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── getResourceFromMedia3p.js │ │ │ │ │ │ ├── useFFmpeg.js │ │ │ │ │ │ ├── useMediaInfo.tsx │ │ │ │ │ │ └── useProcessMedia.js │ │ │ │ │ ├── useDetectBaseColor.ts │ │ │ │ │ ├── useDetectBlurhash.js │ │ │ │ │ ├── useDetectVideoHasAudio.ts │ │ │ │ │ ├── useFFmpeg.ts │ │ │ │ │ ├── useMediaInfo.ts │ │ │ │ │ ├── useProcessMedia.ts │ │ │ │ │ ├── useUpdateElementDimensions.ts │ │ │ │ │ ├── useUploadVideoFrame.ts │ │ │ │ │ └── useVideoElementTranscoding.js │ │ │ │ ├── pageCanvas/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── getPageWithoutSelection.ts │ │ │ │ │ ├── getPixelDataFromCanvas.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── pageCanvasCacheValidator.ts │ │ │ │ │ ├── pageCanvasProvider.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── usePageCanvas.js │ │ │ │ │ ├── testUtils/ │ │ │ │ │ │ ├── createMockPage.js │ │ │ │ │ │ └── useStoryMock.js │ │ │ │ │ ├── useCalculateAccessibleTextColors.ts │ │ │ │ │ ├── usePageCanvas.ts │ │ │ │ │ ├── usePageCanvasMap.ts │ │ │ │ │ ├── usePageSnapshot.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── storyPageToCanvas.ts │ │ │ │ │ ├── storyPageToDataUrl.ts │ │ │ │ │ └── storyPageToNode.tsx │ │ │ │ ├── pageDataUrls/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── pageDataUrlsProvider.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── usePageDataUrls.js │ │ │ │ │ └── usePageDataUrls.ts │ │ │ │ ├── quickActions/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mediaPicker.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── useQuickActions.js │ │ │ │ │ ├── useElementReset.js │ │ │ │ │ ├── useForegroundActions.js │ │ │ │ │ ├── useMediaActions.js │ │ │ │ │ ├── useQuickActions.js │ │ │ │ │ ├── useTextActions.js │ │ │ │ │ └── utils/ │ │ │ │ │ ├── getResetProperties.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── getResetProperties.js │ │ │ │ ├── rightClickMenu/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── testUtils.js │ │ │ │ │ │ │ ├── useCopyPasteActions.js │ │ │ │ │ │ │ ├── useElementActions.js │ │ │ │ │ │ │ ├── useLayerActions.js │ │ │ │ │ │ │ ├── usePageActions.js │ │ │ │ │ │ │ └── usePresetActions.js │ │ │ │ │ │ ├── useCopyPasteActions.js │ │ │ │ │ │ ├── useElementActions.js │ │ │ │ │ │ ├── useHeadingSelect.js │ │ │ │ │ │ ├── useLayerActions.js │ │ │ │ │ │ ├── usePageActions.js │ │ │ │ │ │ └── usePresetActions.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── items/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── layerHide.js │ │ │ │ │ │ ├── layerLock.js │ │ │ │ │ │ ├── layerName.js │ │ │ │ │ │ └── layerUngroup.js │ │ │ │ │ ├── menus/ │ │ │ │ │ │ ├── emptyStateMenu.js │ │ │ │ │ │ ├── foregroundMediaMenu.js │ │ │ │ │ │ ├── groupMenu.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── multipleElementsMenu.js │ │ │ │ │ │ ├── pageMenu.js │ │ │ │ │ │ ├── productMenu.js │ │ │ │ │ │ ├── shapeMenu.js │ │ │ │ │ │ ├── shared.js │ │ │ │ │ │ ├── stickerMenu.js │ │ │ │ │ │ └── textMenu.js │ │ │ │ │ ├── provider.js │ │ │ │ │ ├── reducer.js │ │ │ │ │ ├── useLayerSelect.js │ │ │ │ │ └── useRightClickMenu.js │ │ │ │ ├── story/ │ │ │ │ │ ├── actions/ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── useAutoSave.js │ │ │ │ │ │ ├── useAutoSave.ts │ │ │ │ │ │ ├── useLocalAutoSave.ts │ │ │ │ │ │ └── useSaveStory.ts │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── effects/ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── useHashState.js │ │ │ │ │ │ │ └── useLoadStory.js │ │ │ │ │ │ ├── useHashState.ts │ │ │ │ │ │ ├── useHistoryEntry.ts │ │ │ │ │ │ ├── useHistoryReplay.ts │ │ │ │ │ │ └── useLoadStory.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── storyProvider.tsx │ │ │ │ │ ├── storyTriggers/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── storyEvents/ │ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ │ ├── onInitialElementAddedRegister.ts │ │ │ │ │ │ │ ├── onPageAddedRegister.ts │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── onInitialElementAddedRegister.js │ │ │ │ │ │ │ │ └── onPageAddedRegister.js │ │ │ │ │ │ │ └── types.ts │ │ │ │ │ │ ├── storyTriggersProvider.tsx │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── useStoryTriggers.js │ │ │ │ │ │ └── useStoryTriggers.ts │ │ │ │ │ ├── useStory.ts │ │ │ │ │ ├── useStoryReducer/ │ │ │ │ │ │ ├── actions.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── reducer.ts │ │ │ │ │ │ ├── reducers/ │ │ │ │ │ │ │ ├── addAnimations.ts │ │ │ │ │ │ │ ├── addElements.ts │ │ │ │ │ │ │ ├── addElementsAcrossPages.ts │ │ │ │ │ │ │ ├── addGroup.ts │ │ │ │ │ │ │ ├── addPage.ts │ │ │ │ │ │ │ ├── arrangeElement.ts │ │ │ │ │ │ │ ├── arrangeGroup.ts │ │ │ │ │ │ │ ├── arrangePage.ts │ │ │ │ │ │ │ ├── combineElements.ts │ │ │ │ │ │ │ ├── copySelectedElement.ts │ │ │ │ │ │ │ ├── deleteElements.ts │ │ │ │ │ │ │ ├── deleteElementsByResourceId.ts │ │ │ │ │ │ │ ├── deleteGroup.ts │ │ │ │ │ │ │ ├── deletePage.ts │ │ │ │ │ │ │ ├── duplicateElementsById.ts │ │ │ │ │ │ │ ├── duplicateGroup.ts │ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ │ ├── removeElementFromGroup.ts │ │ │ │ │ │ │ ├── restore.ts │ │ │ │ │ │ │ ├── selectElement.ts │ │ │ │ │ │ │ ├── setBackgroundElement.ts │ │ │ │ │ │ │ ├── setCurrentPage.ts │ │ │ │ │ │ │ ├── setSelectedElements.ts │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── utils.js │ │ │ │ │ │ │ ├── toggleElement.ts │ │ │ │ │ │ │ ├── toggleLayer.ts │ │ │ │ │ │ │ ├── unselectElement.ts │ │ │ │ │ │ │ ├── updateAnimationState.ts │ │ │ │ │ │ │ ├── updateElements.ts │ │ │ │ │ │ │ ├── updateElementsByFontFamily.ts │ │ │ │ │ │ │ ├── updateElementsByResourceId.ts │ │ │ │ │ │ │ ├── updateGroup.ts │ │ │ │ │ │ │ ├── updatePage.ts │ │ │ │ │ │ │ ├── updateStory.ts │ │ │ │ │ │ │ └── utils.ts │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ │ ├── addAnimations.js │ │ │ │ │ │ │ ├── addElement.js │ │ │ │ │ │ │ ├── addElementToSelection.js │ │ │ │ │ │ │ ├── addElements.js │ │ │ │ │ │ │ ├── addElementsAcrossPages.js │ │ │ │ │ │ │ ├── addGroup.js │ │ │ │ │ │ │ ├── addPage.js │ │ │ │ │ │ │ ├── addPageAt.js │ │ │ │ │ │ │ ├── arrangeElement.js │ │ │ │ │ │ │ ├── arrangeGroup.js │ │ │ │ │ │ │ ├── arrangePage.js │ │ │ │ │ │ │ ├── arrangeSelection.js │ │ │ │ │ │ │ ├── clearBackgroundElement.js │ │ │ │ │ │ │ ├── clearSelection.js │ │ │ │ │ │ │ ├── combineElements.js │ │ │ │ │ │ │ ├── copySelectedElement.js │ │ │ │ │ │ │ ├── deleteCurrentPage.js │ │ │ │ │ │ │ ├── deleteElementById.js │ │ │ │ │ │ │ ├── deleteElementsById.js │ │ │ │ │ │ │ ├── deleteElementsByResourceId.js │ │ │ │ │ │ │ ├── deleteGroupAndElementsById.js │ │ │ │ │ │ │ ├── deleteGroupById.js │ │ │ │ │ │ │ ├── deletePage.js │ │ │ │ │ │ │ ├── deleteSelectedElements.js │ │ │ │ │ │ │ ├── duplicateElementsById.js │ │ │ │ │ │ │ ├── duplicateGroupById.js │ │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ │ ├── removeElementFromGroup.js │ │ │ │ │ │ │ ├── removeElementFromSelection.js │ │ │ │ │ │ │ ├── restore.js │ │ │ │ │ │ │ ├── setBackgroundElement.js │ │ │ │ │ │ │ ├── setCurrentPage.js │ │ │ │ │ │ │ ├── setSelectedElementsById.js │ │ │ │ │ │ │ ├── toggleElementInSelection.js │ │ │ │ │ │ │ ├── toggleLayer.js │ │ │ │ │ │ │ ├── updateAnimationState.js │ │ │ │ │ │ │ ├── updateCurrentPageProperties.js │ │ │ │ │ │ │ ├── updateElementById.js │ │ │ │ │ │ │ ├── updateElementsByFontFamily.js │ │ │ │ │ │ │ ├── updateElementsById.js │ │ │ │ │ │ │ ├── updateElementsByResourceId.js │ │ │ │ │ │ │ ├── updateGroupById.js │ │ │ │ │ │ │ ├── updatePageProperties.js │ │ │ │ │ │ │ ├── updateSelectedElements.js │ │ │ │ │ │ │ └── updateStory.js │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ └── useStoryReducer.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── cleanElementFontProperties.ts │ │ │ │ │ ├── deleteNestedKeys.ts │ │ │ │ │ ├── getAllProducts.ts │ │ │ │ │ ├── getStoryFontsFromPages.ts │ │ │ │ │ ├── getStoryPropsToSave.ts │ │ │ │ │ ├── isEmptyStory.ts │ │ │ │ │ ├── pageContainsBlobUrl.ts │ │ │ │ │ └── test/ │ │ │ │ │ ├── cleanElementFontPropties.js │ │ │ │ │ ├── deleteNestedKeys.js │ │ │ │ │ ├── getAllProduct.js │ │ │ │ │ ├── getStoryFontsFromPages.js │ │ │ │ │ ├── getStoryPropsToSave.js │ │ │ │ │ ├── isEmptyStory.js │ │ │ │ │ └── pageContainsBlobUrl.js │ │ │ │ ├── taxonomy/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── taxonomyProvider.tsx │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── useTaxonomy.js │ │ │ │ │ └── useTaxonomy.ts │ │ │ │ ├── uploader/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── useUploader.js │ │ │ │ │ └── useUploader.ts │ │ │ │ └── userOnboarding/ │ │ │ │ ├── index.js │ │ │ │ ├── test/ │ │ │ │ │ └── useUserOnboarding.js │ │ │ │ └── useUserOnboarding.js │ │ │ ├── components/ │ │ │ │ ├── autoSaveCheck/ │ │ │ │ │ ├── autoSaveDialog.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── autoSaveDialog.js │ │ │ │ ├── autoSaveHandler/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── autoSaveHandler.js │ │ │ │ ├── canvas/ │ │ │ │ │ ├── canvas.js │ │ │ │ │ ├── canvasElementDropzone.js │ │ │ │ │ ├── canvasLayout.js │ │ │ │ │ ├── canvasUploadDropTarget.js │ │ │ │ │ ├── displayElement.d.ts │ │ │ │ │ ├── displayElement.js │ │ │ │ │ ├── displayLayer.js │ │ │ │ │ ├── editElement.js │ │ │ │ │ ├── editLayer.js │ │ │ │ │ ├── editLayerFocusManager/ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── context.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── keyBindings.js │ │ │ │ │ │ ├── provider.js │ │ │ │ │ │ ├── reduction.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── EditLayerFocusManager.js │ │ │ │ │ │ ├── useEditLayerFocusManager.js │ │ │ │ │ │ └── useFocusGroupRef.js │ │ │ │ │ ├── emptyStateLayer.js │ │ │ │ │ ├── extraPages.js │ │ │ │ │ ├── eyedropperLayer.js │ │ │ │ │ ├── frameElement.js │ │ │ │ │ ├── framesLayer.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── backgroundCopyPaste.karma.js │ │ │ │ │ │ ├── canvasKeyboardNavigation.karma.js │ │ │ │ │ │ ├── canvasKeys.karma.js │ │ │ │ │ │ ├── carousel.karma.js │ │ │ │ │ │ ├── cloneSelection.karma.js │ │ │ │ │ │ ├── elementKeyboardNavigation.js │ │ │ │ │ │ ├── fullbleedMediaAsBackground.karma.js │ │ │ │ │ │ ├── keys.karma.js │ │ │ │ │ │ ├── lasso.karma.js │ │ │ │ │ │ ├── multiSelectionMovable.karma.js │ │ │ │ │ │ ├── pageMenuActions.karma.js │ │ │ │ │ │ ├── pageSideMenuActions.karma.js │ │ │ │ │ │ ├── quickActions.karma.js │ │ │ │ │ │ ├── rightClickMenu.karma.js │ │ │ │ │ │ ├── rtl.karma.js │ │ │ │ │ │ ├── selection.karma.js │ │ │ │ │ │ └── snapping.karma.js │ │ │ │ │ ├── layout.js │ │ │ │ │ ├── mediaCaptions/ │ │ │ │ │ │ ├── cue.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── mediaCaptionsLayer.js │ │ │ │ │ │ ├── parseTimestamp.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── parseTimestamp.js │ │ │ │ │ │ └── trackRenderer.js │ │ │ │ │ ├── mediaRecordingLayer.js │ │ │ │ │ ├── multiSelectionMoveable/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── useDrag.js │ │ │ │ │ │ ├── useResize.js │ │ │ │ │ │ └── useRotate.js │ │ │ │ │ ├── navLayer.js │ │ │ │ │ ├── pageAttachment/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ └── pageAttachment.cuj.karma.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── pageAttachment.js │ │ │ │ │ ├── pageSideMenu.js │ │ │ │ │ ├── pagemenu/ │ │ │ │ │ │ ├── animationToggle.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── pageMenu.js │ │ │ │ │ │ └── pageMenuButton.js │ │ │ │ │ ├── pagenav/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── renderResourcePlaceholder.js │ │ │ │ │ ├── rightClickMenu.js │ │ │ │ │ ├── selection.js │ │ │ │ │ ├── selectionCanvas.js │ │ │ │ │ ├── shoppingPageAttachment/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── singleSelectionMoveable/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── useDrag.js │ │ │ │ │ │ ├── useResize.js │ │ │ │ │ │ └── useRotate.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ │ └── mediaDisplay.js.snap │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ ├── frame.js │ │ │ │ │ │ ├── frameElement.js │ │ │ │ │ │ ├── mediaDisplay.js │ │ │ │ │ │ ├── multiSelectionMoveable.js │ │ │ │ │ │ ├── singleSelectionMoveable.js │ │ │ │ │ │ ├── useCanvasKeys.js │ │ │ │ │ │ └── useInsertElement.js │ │ │ │ │ ├── useFocusCanvas.ts │ │ │ │ │ ├── useInsertElement.ts │ │ │ │ │ ├── useInsertTextSet.js │ │ │ │ │ ├── usePinchToZoom.js │ │ │ │ │ ├── useUploadWithPreview.d.ts │ │ │ │ │ ├── useUploadWithPreview.js │ │ │ │ │ ├── useWindowResizeHandler.js │ │ │ │ │ └── utils/ │ │ │ │ │ ├── getColorFromPixelData.js │ │ │ │ │ ├── getElementProperties.ts │ │ │ │ │ ├── normalizeRotationDegrees.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── getElementProperties.js │ │ │ │ │ ├── useElementOutOfCanvas.js │ │ │ │ │ ├── useFullbleedMediaAsBackground.js │ │ │ │ │ ├── useSnapping.js │ │ │ │ │ └── useUpdateSelectionRectangle.js │ │ │ │ ├── checklist/ │ │ │ │ │ ├── checklist.js │ │ │ │ │ ├── checklistContent/ │ │ │ │ │ │ ├── accessibilityChecks.js │ │ │ │ │ │ ├── designChecks.js │ │ │ │ │ │ ├── emptyContent.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── priorityChecks.js │ │ │ │ │ ├── checklistContext/ │ │ │ │ │ │ ├── context.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── provider.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── useChecklist.js │ │ │ │ │ │ └── useChecklist.js │ │ │ │ │ ├── checklistIcon.js │ │ │ │ │ ├── checkpointContext/ │ │ │ │ │ │ ├── checkpointContext.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── checks/ │ │ │ │ │ │ ├── elementLinkTappableRegionTooBig.js │ │ │ │ │ │ ├── elementLinkTappableRegionTooSmall.js │ │ │ │ │ │ ├── firstPageAnimation.js │ │ │ │ │ │ ├── imageElementMissingAlt.js │ │ │ │ │ │ ├── imageElementResolution.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── pageBackgroundLowTextContrast/ │ │ │ │ │ │ │ ├── check.js │ │ │ │ │ │ │ ├── component.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── pageTooLittleText.js │ │ │ │ │ │ ├── pageTooManyLinks.js │ │ │ │ │ │ ├── pageTooMuchText.js │ │ │ │ │ │ ├── publisherLogoMissing.js │ │ │ │ │ │ ├── publisherLogoSize.js │ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── thumbnailWrapper.js │ │ │ │ │ │ │ ├── thumbnailWrapper.js │ │ │ │ │ │ │ └── videoChecklistCard.js │ │ │ │ │ │ ├── storyAmpValidationErrors.js │ │ │ │ │ │ ├── storyMissingExcerpt.js │ │ │ │ │ │ ├── storyMissingTitle.js │ │ │ │ │ │ ├── storyPagesCount.js │ │ │ │ │ │ ├── storyPosterAttached.js │ │ │ │ │ │ ├── storyPosterSize.js │ │ │ │ │ │ ├── storyTitleLength.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── elementLinkTappableRegionTooBig.js │ │ │ │ │ │ │ ├── elementLinkTappableRegionTooSmall.js │ │ │ │ │ │ │ ├── firstPageAnimation.js │ │ │ │ │ │ │ ├── imageElementMissingAlt.js │ │ │ │ │ │ │ ├── imageElementResolution.js │ │ │ │ │ │ │ ├── pageBackgroundLowTextContrast.js │ │ │ │ │ │ │ ├── pageTooLittleText.js │ │ │ │ │ │ │ ├── pageTooManyLinks.js │ │ │ │ │ │ │ ├── pageTooMuchText.js │ │ │ │ │ │ │ ├── publisherLogoMissing.js │ │ │ │ │ │ │ ├── publisherLogoSize.js │ │ │ │ │ │ │ ├── storyAmpValidationErrors.js │ │ │ │ │ │ │ ├── storyMissingExcerpt.js │ │ │ │ │ │ │ ├── storyMissingTitle.js │ │ │ │ │ │ │ ├── storyPagesCount.js │ │ │ │ │ │ │ ├── storyPosterAttached.js │ │ │ │ │ │ │ ├── storyPosterSize.js │ │ │ │ │ │ │ ├── storyTitleLength.js │ │ │ │ │ │ │ ├── textElementFontSizeTooSmall.js │ │ │ │ │ │ │ ├── videoElementLength.js │ │ │ │ │ │ │ ├── videoElementMissingCaptions.js │ │ │ │ │ │ │ ├── videoElementMissingDescription.js │ │ │ │ │ │ │ ├── videoElementMissingPoster.js │ │ │ │ │ │ │ ├── videoElementResolution.js │ │ │ │ │ │ │ └── videoOptimization.js │ │ │ │ │ │ ├── textElementFontSizeTooSmall.js │ │ │ │ │ │ ├── videoElementLength.js │ │ │ │ │ │ ├── videoElementMissingCaptions.js │ │ │ │ │ │ ├── videoElementMissingDescription.js │ │ │ │ │ │ ├── videoElementMissingPoster.js │ │ │ │ │ │ ├── videoElementResolution.js │ │ │ │ │ │ └── videoOptimization.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── countContext/ │ │ │ │ │ │ ├── checkCountContext.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── checkCountContext.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── checklist.karma.js │ │ │ │ │ │ ├── firstPageAnimation.karma.js │ │ │ │ │ │ └── prepublishSelect.karma.js │ │ │ │ │ ├── popupMountedContext.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ ├── toggle/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── utils/ │ │ │ │ │ ├── characterCountForPage.js │ │ │ │ │ ├── filterStoryElements.js │ │ │ │ │ ├── filterStoryPages.js │ │ │ │ │ ├── getVisibleThumbnails.js │ │ │ │ │ ├── hasNoFeaturedMedia.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── filterStoryElements.js │ │ │ │ │ │ └── filterStoryPages.js │ │ │ │ │ └── thumbnailPagePreview.js │ │ │ │ ├── checklistCard/ │ │ │ │ │ ├── checkboxCta.js │ │ │ │ │ ├── checklistCard.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── defaultCtaButton.js │ │ │ │ │ ├── defaultFooterText.js │ │ │ │ │ ├── helpers/ │ │ │ │ │ │ ├── getGridVariant.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── colorPicker/ │ │ │ │ │ ├── addCustomColor.js │ │ │ │ │ ├── basicColorList.js │ │ │ │ │ ├── basicColorPicker.js │ │ │ │ │ ├── colorAdd.js │ │ │ │ │ ├── colorPicker.js │ │ │ │ │ ├── confirmationDialog.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── currentColorPicker.js │ │ │ │ │ ├── customColorPicker.js │ │ │ │ │ ├── editablePreview.js │ │ │ │ │ ├── gradientLine.js │ │ │ │ │ ├── gradientPicker.js │ │ │ │ │ ├── gradientStop.js │ │ │ │ │ ├── header.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── insertStop.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── colorPicker.karma.js │ │ │ │ │ │ └── eyedropper.karma.js │ │ │ │ │ ├── patternTypePicker.js │ │ │ │ │ ├── pointer.js │ │ │ │ │ ├── regenerateColor.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── colorPicker/ │ │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ │ ├── addStopByPointer.js │ │ │ │ │ │ │ ├── colorInteraction.js │ │ │ │ │ │ │ ├── footerInteraction.js │ │ │ │ │ │ │ ├── headerInteraction.js │ │ │ │ │ │ │ ├── manipulateGradient.js │ │ │ │ │ │ │ ├── manipulateStopByKeyboard.js │ │ │ │ │ │ │ ├── moveStopByPointer.js │ │ │ │ │ │ │ ├── onclose.js │ │ │ │ │ │ │ ├── onload.js │ │ │ │ │ │ │ ├── savedColors.js │ │ │ │ │ │ │ └── selectStop.js │ │ │ │ │ │ ├── insertStop.js │ │ │ │ │ │ ├── regenerateColor.js │ │ │ │ │ │ └── useColor/ │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ ├── addStopAt.js │ │ │ │ │ │ ├── load.js │ │ │ │ │ │ ├── moveCurrentStopBy.js │ │ │ │ │ │ ├── removeCurrentStop.js │ │ │ │ │ │ ├── reverseStops.js │ │ │ │ │ │ ├── rotateClockwise.js │ │ │ │ │ │ ├── selectStop.js │ │ │ │ │ │ ├── setToGradient.js │ │ │ │ │ │ ├── setToSolid.js │ │ │ │ │ │ └── updateCurrentColor.js │ │ │ │ │ ├── useColor.js │ │ │ │ │ ├── useDeleteColor.js │ │ │ │ │ ├── useKeyAddStop.js │ │ │ │ │ ├── useKeyDeleteStop.js │ │ │ │ │ ├── useKeyFocus.js │ │ │ │ │ ├── useKeyMoveStop.js │ │ │ │ │ ├── usePointerAddStop.js │ │ │ │ │ ├── usePointerMoveStop.js │ │ │ │ │ └── utils.js │ │ │ │ ├── devTools/ │ │ │ │ │ ├── devTools.js │ │ │ │ │ ├── dummyData.js │ │ │ │ │ └── index.js │ │ │ │ ├── dialog/ │ │ │ │ │ ├── dialog.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── directionAware/ │ │ │ │ │ └── index.js │ │ │ │ ├── dropTargets/ │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── dropTarget.karma.js │ │ │ │ │ │ └── order.karma.js │ │ │ │ │ ├── provider.js │ │ │ │ │ └── useDropTargets.js │ │ │ │ ├── elementLink/ │ │ │ │ │ ├── frame.js │ │ │ │ │ └── index.js │ │ │ │ ├── emptyContentMessage.js │ │ │ │ ├── errorBoundary/ │ │ │ │ │ ├── copyStoryDataToClipboard.js │ │ │ │ │ ├── errorActions.js │ │ │ │ │ └── index.js │ │ │ │ ├── eyedropper/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── useEyeDropperApi.js │ │ │ │ ├── floatingMenu/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── context/ │ │ │ │ │ │ ├── context.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── provider.js │ │ │ │ │ │ └── use.js │ │ │ │ │ ├── elements/ │ │ │ │ │ │ ├── borderRadius.js │ │ │ │ │ │ ├── borderWidthAndColor.js │ │ │ │ │ │ ├── dismiss.js │ │ │ │ │ │ ├── elementAlignment.js │ │ │ │ │ │ ├── flipHorizontal.js │ │ │ │ │ │ ├── flipVertical.js │ │ │ │ │ │ ├── fontFamily.js │ │ │ │ │ │ ├── fontSize.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ ├── border.karma.js │ │ │ │ │ │ │ ├── borderRadius.karma.js │ │ │ │ │ │ │ ├── flip.karma.js │ │ │ │ │ │ │ ├── loop.karma.js │ │ │ │ │ │ │ ├── more.karma.js │ │ │ │ │ │ │ ├── opacity.karma.js │ │ │ │ │ │ │ ├── shopping.karma.js │ │ │ │ │ │ │ ├── text.karma.js │ │ │ │ │ │ │ └── textAlign.karma.js │ │ │ │ │ │ ├── layerOpacity.js │ │ │ │ │ │ ├── loop.js │ │ │ │ │ │ ├── more.js │ │ │ │ │ │ ├── mute.js │ │ │ │ │ │ ├── settings.js │ │ │ │ │ │ ├── shapeColor.js │ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ │ ├── color.js │ │ │ │ │ │ │ ├── focusTrapButton.js │ │ │ │ │ │ │ ├── icon.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── input.js │ │ │ │ │ │ │ ├── separator.js │ │ │ │ │ │ │ ├── text.js │ │ │ │ │ │ │ ├── toggleButton.js │ │ │ │ │ │ │ ├── useFlip.ts │ │ │ │ │ │ │ ├── useProperties.ts │ │ │ │ │ │ │ └── useTextToggle.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── mute.js │ │ │ │ │ │ │ └── trim.js │ │ │ │ │ │ ├── textAlign.js │ │ │ │ │ │ ├── textColor.js │ │ │ │ │ │ ├── toggleBold.js │ │ │ │ │ │ ├── toggleItalics.js │ │ │ │ │ │ ├── toggleUnderline.js │ │ │ │ │ │ ├── trash.js │ │ │ │ │ │ └── trim.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── floatingMenu.karma.js │ │ │ │ │ │ ├── image.karma.js │ │ │ │ │ │ ├── shape.karma.js │ │ │ │ │ │ ├── sticker.karma.js │ │ │ │ │ │ ├── text.karma.js │ │ │ │ │ │ ├── utils.js │ │ │ │ │ │ └── video.karma.js │ │ │ │ │ ├── layer.js │ │ │ │ │ ├── menu.js │ │ │ │ │ ├── menus/ │ │ │ │ │ │ ├── audioSticker.js │ │ │ │ │ │ ├── image.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── multiple.js │ │ │ │ │ │ ├── product.js │ │ │ │ │ │ ├── selector.js │ │ │ │ │ │ ├── shape.js │ │ │ │ │ │ ├── sticker.js │ │ │ │ │ │ ├── text.js │ │ │ │ │ │ └── video.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── fontPicker/ │ │ │ │ │ └── index.js │ │ │ │ ├── footer/ │ │ │ │ │ ├── carousel/ │ │ │ │ │ │ ├── carouselContainer.js │ │ │ │ │ │ ├── carouselContext/ │ │ │ │ │ │ │ ├── carouselProvider.tsx │ │ │ │ │ │ │ ├── context.ts │ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ │ ├── useCarousel.ts │ │ │ │ │ │ │ ├── useCarouselKeys.ts │ │ │ │ │ │ │ ├── useCarouselScroll.ts │ │ │ │ │ │ │ └── useCarouselSizing.ts │ │ │ │ │ │ ├── carouselDrawer.js │ │ │ │ │ │ ├── carouselDrawerIcon.js │ │ │ │ │ │ ├── carouselLayout.js │ │ │ │ │ │ ├── carouselList.js │ │ │ │ │ │ ├── carouselPage.js │ │ │ │ │ │ ├── carouselScroll.js │ │ │ │ │ │ ├── constants.ts │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ ├── carouselDrawer.karma.js │ │ │ │ │ │ │ └── carouselNavigation.karma.js │ │ │ │ │ │ └── skeletonPage.tsx │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── footer.js │ │ │ │ │ ├── footerLayout.js │ │ │ │ │ ├── gridview/ │ │ │ │ │ │ ├── gridView.js │ │ │ │ │ │ ├── gridViewButton.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ └── gridView.karma.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── gridview.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── footerMenu.karma.js │ │ │ │ │ │ ├── popups.karma.js │ │ │ │ │ │ └── zoomSelector.karma.js │ │ │ │ │ ├── layers/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── layers.js │ │ │ │ │ ├── pagepreview/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── primaryMenu.js │ │ │ │ │ ├── secondaryMenu.js │ │ │ │ │ ├── toolbarToggle.js │ │ │ │ │ ├── useFooterHeight.js │ │ │ │ │ └── zoomSelector/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── zoomSelector.js │ │ │ │ ├── form/ │ │ │ │ │ ├── color/ │ │ │ │ │ │ ├── activeOpacity.js │ │ │ │ │ │ ├── applyOpacityChange.js │ │ │ │ │ │ ├── color.js │ │ │ │ │ │ ├── colorInput.js │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── getPreviewOpacity.js │ │ │ │ │ │ ├── getPreviewStyle.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── opacityInput.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ ├── applyOpacityChange.js │ │ │ │ │ │ ├── color.js │ │ │ │ │ │ ├── colorInput.js │ │ │ │ │ │ ├── getPreviewOpacity.js │ │ │ │ │ │ ├── getPreviewStyle.js │ │ │ │ │ │ └── opacityInput.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── dateTime/ │ │ │ │ │ │ ├── calendarWrapper.js │ │ │ │ │ │ ├── datePicker.js │ │ │ │ │ │ ├── dateTime.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── timePicker.js │ │ │ │ │ │ ├── timeZone.js │ │ │ │ │ │ └── utils.js │ │ │ │ │ ├── filterToggle/ │ │ │ │ │ │ ├── filterToggle.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── hierarchical/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── hierarchical.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── hierarchical.js │ │ │ │ │ │ │ └── utils.js │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── link.js │ │ │ │ │ ├── linkIcon.js │ │ │ │ │ ├── media.js │ │ │ │ │ ├── mediaUploadButton.js │ │ │ │ │ ├── radioGroup/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── required.js │ │ │ │ │ ├── row.js │ │ │ │ │ ├── select/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── select.js │ │ │ │ │ ├── shared/ │ │ │ │ │ │ └── useRadioNavigation.js │ │ │ │ │ ├── stackable/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stackableGroup.js │ │ │ │ │ │ └── stackableInput.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── link.js │ │ │ │ │ │ ├── radioGroup.js │ │ │ │ │ │ ├── switch.js │ │ │ │ │ │ └── tags.js │ │ │ │ │ ├── switch.js │ │ │ │ │ ├── tags/ │ │ │ │ │ │ ├── description.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── input.js │ │ │ │ │ │ ├── label.js │ │ │ │ │ │ ├── reducer.js │ │ │ │ │ │ ├── tag.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ ├── input.js │ │ │ │ │ │ └── reducer.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── radioGroup.js │ │ │ │ │ │ └── switch.js │ │ │ │ │ ├── textArea.js │ │ │ │ │ ├── useFormContext.js │ │ │ │ │ ├── useHotlink.js │ │ │ │ │ └── usePresubmitHandler.js │ │ │ │ ├── header/ │ │ │ │ │ ├── buttons/ │ │ │ │ │ │ ├── buttonWithChecklistWarning.js │ │ │ │ │ │ ├── historyButtons.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── preview.js │ │ │ │ │ │ ├── publish.js │ │ │ │ │ │ ├── switchToDraft.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── preview.js │ │ │ │ │ │ │ ├── publish.js │ │ │ │ │ │ │ ├── switchToDraft.js │ │ │ │ │ │ │ └── update.js │ │ │ │ │ │ └── update.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── previewErrorDialog.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── previewErrorDialog.js │ │ │ │ │ └── title.js │ │ │ │ ├── helpCenter/ │ │ │ │ │ ├── companion/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── helpCenter.karma.js │ │ │ │ │ ├── menu/ │ │ │ │ │ │ ├── header.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── tips.js │ │ │ │ │ │ └── transitioner.js │ │ │ │ │ ├── navigator/ │ │ │ │ │ │ ├── bottomNavigation.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── utils.js │ │ │ │ │ ├── quickTip/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── transitioner.js │ │ │ │ │ ├── toggle/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── utils.js │ │ │ │ ├── hideOnError.tsx │ │ │ │ ├── hotlinkModal/ │ │ │ │ │ ├── hotlinkModal.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── hotlinkDialog.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── isValidUrlForHotlinking.js │ │ │ │ │ ├── useHotlinkModal.js │ │ │ │ │ └── utils.js │ │ │ │ ├── keyboardShortcutsMenu/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── headerShortcut.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── keyboardShortcuts.karma.js │ │ │ │ │ ├── keyboardShortcutList.js │ │ │ │ │ ├── keyboardShortcutsMenuContext/ │ │ │ │ │ │ ├── context.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── provider.tsx │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ └── useKeyboardShortcutsMenu.ts │ │ │ │ │ ├── landmarkShortcuts.js │ │ │ │ │ ├── regularShortcuts.js │ │ │ │ │ ├── shortcutLabel.js │ │ │ │ │ ├── shortcutMenu.js │ │ │ │ │ ├── shortcutMenuSection.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── layout/ │ │ │ │ │ └── index.js │ │ │ │ ├── library/ │ │ │ │ │ ├── common/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── searchInput.js │ │ │ │ │ │ ├── section.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── searchInput.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ ├── libraryTabs.karma.js │ │ │ │ │ │ ├── mediaTab.karma.js │ │ │ │ │ │ └── shapes/ │ │ │ │ │ │ └── shapes.karma.js │ │ │ │ │ ├── library.js │ │ │ │ │ ├── libraryLayout.js │ │ │ │ │ ├── libraryPanes.js │ │ │ │ │ ├── libraryProvider.js │ │ │ │ │ ├── libraryUploadDropTarget.js │ │ │ │ │ ├── paneIds.ts │ │ │ │ │ ├── panes/ │ │ │ │ │ │ ├── common/ │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ ├── media/ │ │ │ │ │ │ │ ├── common/ │ │ │ │ │ │ │ │ ├── attribution.js │ │ │ │ │ │ │ │ ├── innerElement.js │ │ │ │ │ │ │ │ ├── insertionMenu.js │ │ │ │ │ │ │ │ ├── mediaElement.js │ │ │ │ │ │ │ │ ├── mediaGallery.js │ │ │ │ │ │ │ │ ├── paginatedMediaGallery.js │ │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ │ ├── mediaElement.js │ │ │ │ │ │ │ │ │ └── mediaGallery.js │ │ │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ │ ├── accessibility.js │ │ │ │ │ │ │ │ └── paginatedMediaGallery.js │ │ │ │ │ │ │ ├── local/ │ │ │ │ │ │ │ │ ├── deleteDialog.js │ │ │ │ │ │ │ │ ├── dropDownMenu.js │ │ │ │ │ │ │ │ ├── hotlink/ │ │ │ │ │ │ │ │ │ ├── hotlink.js │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── useInsert.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ │ ├── hotlink.karma.js │ │ │ │ │ │ │ │ │ └── mediaFetching.karma.js │ │ │ │ │ │ │ │ ├── mediaEditDialog.js │ │ │ │ │ │ │ │ ├── mediaIcon.js │ │ │ │ │ │ │ │ ├── mediaPane.js │ │ │ │ │ │ │ │ ├── mediaRecording/ │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── mediaRecording.js │ │ │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ │ ├── deleteDialog.js │ │ │ │ │ │ │ │ │ ├── mediaEditDialog.js │ │ │ │ │ │ │ │ │ └── videoOptimizationDialog.js │ │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ │ └── videoOptimizationDialog.js │ │ │ │ │ │ │ │ ├── useOnMediaSelect.js │ │ │ │ │ │ │ │ └── videoOptimizationDialog.js │ │ │ │ │ │ │ └── media3p/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── mediaFetching.karma.js │ │ │ │ │ │ │ ├── media3pIcon.js │ │ │ │ │ │ │ ├── media3pPane.js │ │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ │ ├── providerPanel.js │ │ │ │ │ │ │ ├── providerTab.js │ │ │ │ │ │ │ ├── providerTabList.js │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ └── termsDialog.js │ │ │ │ │ │ │ ├── termsDialog.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ ├── accessibility.js │ │ │ │ │ │ │ └── media3pPane.js │ │ │ │ │ │ ├── pageTemplates/ │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ ├── defaultPageTemplate.js │ │ │ │ │ │ │ ├── defaultTemplates.js │ │ │ │ │ │ │ ├── deleteDialog.js │ │ │ │ │ │ │ ├── dropDownMenu.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ ├── defaultPageTemplates.karma.js │ │ │ │ │ │ │ │ └── savedPageTemplates.karma.js │ │ │ │ │ │ │ ├── nameDialog.js │ │ │ │ │ │ │ ├── pageTemplatesIcon.js │ │ │ │ │ │ │ ├── pageTemplatesPane.js │ │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ │ ├── savedPageTemplate.js │ │ │ │ │ │ │ ├── savedTemplates.js │ │ │ │ │ │ │ ├── templateList.js │ │ │ │ │ │ │ └── templateSave.js │ │ │ │ │ │ ├── shapes/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ │ ├── shapePreview.js │ │ │ │ │ │ │ ├── shapesIcon.js │ │ │ │ │ │ │ ├── shapesPane.js │ │ │ │ │ │ │ └── stickerPreview.js │ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ │ ├── chipGroup/ │ │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── stories/ │ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ ├── useExpandAnimation.js │ │ │ │ │ │ │ │ └── useHandleRowVisibility.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── insertionOverlay.js │ │ │ │ │ │ │ ├── libraryMoveable.js │ │ │ │ │ │ │ └── virtualizedPanelGrid/ │ │ │ │ │ │ │ ├── components.js │ │ │ │ │ │ │ ├── getVirtualizedItemIndex.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── getVirtualizedItemIndex.js │ │ │ │ │ │ │ │ └── useVirtualizedGridNavigation.js │ │ │ │ │ │ │ └── useVirtualizedGridNavigation.js │ │ │ │ │ │ ├── shopping/ │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── shopping.karma.js │ │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ │ ├── product.js │ │ │ │ │ │ │ ├── productButton.js │ │ │ │ │ │ │ ├── productDropdown.js │ │ │ │ │ │ │ ├── productImage.js │ │ │ │ │ │ │ ├── productList.js │ │ │ │ │ │ │ ├── productPrice.js │ │ │ │ │ │ │ ├── productSort.js │ │ │ │ │ │ │ ├── shoppingIcon.js │ │ │ │ │ │ │ ├── shoppingPane.js │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ │ └── useProductNavigation.js │ │ │ │ │ │ └── text/ │ │ │ │ │ │ ├── fontPreview.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ ├── savedStyles.karma.js │ │ │ │ │ │ │ ├── textPane.karma.js │ │ │ │ │ │ │ └── textSets.cuj.karma.js │ │ │ │ │ │ ├── paneId.js │ │ │ │ │ │ ├── stylePresets/ │ │ │ │ │ │ │ └── stylePresets.js │ │ │ │ │ │ ├── textIcon.js │ │ │ │ │ │ ├── textPane.js │ │ │ │ │ │ ├── textPresets.ts │ │ │ │ │ │ ├── textSets/ │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ └── textSet.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── textSet.js │ │ │ │ │ │ │ │ └── textSetsPane.js │ │ │ │ │ │ │ ├── textSet.js │ │ │ │ │ │ │ ├── textSetElements.js │ │ │ │ │ │ │ ├── textSets.js │ │ │ │ │ │ │ └── textSetsPane.js │ │ │ │ │ │ └── useInsertPreset.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── _utils/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── deleteDialog.js │ │ │ │ │ │ ├── mediaEditDialog.js │ │ │ │ │ │ ├── mediaElement.js │ │ │ │ │ │ ├── shapes/ │ │ │ │ │ │ │ ├── shapePreview.js │ │ │ │ │ │ │ └── stickerPreview.js │ │ │ │ │ │ ├── termsDialog.js │ │ │ │ │ │ └── text/ │ │ │ │ │ │ └── textPane.js │ │ │ │ │ └── useLibrary.js │ │ │ │ ├── localAutoSaveHandler/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── localAutoSave.js │ │ │ │ │ └── test/ │ │ │ │ │ └── localAutoSaveHandler.js │ │ │ │ ├── mediaRecording/ │ │ │ │ │ ├── audio.js │ │ │ │ │ ├── blur.js │ │ │ │ │ ├── components.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── countdown.js │ │ │ │ │ ├── durationIndicator.js │ │ │ │ │ ├── errorDialog.js │ │ │ │ │ ├── footer.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── mediaRecording.karma.js │ │ │ │ │ ├── mediaRecording.js │ │ │ │ │ ├── permissionsDialog.js │ │ │ │ │ ├── playPauseButton.js │ │ │ │ │ ├── playbackMedia.js │ │ │ │ │ ├── processingOverlay.js │ │ │ │ │ ├── progressBar.js │ │ │ │ │ ├── provider.js │ │ │ │ │ ├── settingsModal.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── countdown.js │ │ │ │ │ │ ├── durationIndicator.js │ │ │ │ │ │ ├── errorDialog.js │ │ │ │ │ │ ├── permissionsDialog.js │ │ │ │ │ │ ├── settingsModal.js │ │ │ │ │ │ └── videoMode.js │ │ │ │ │ ├── useMediaRecording.js │ │ │ │ │ ├── useTrim.js │ │ │ │ │ └── videoMode.js │ │ │ │ ├── panels/ │ │ │ │ │ ├── design/ │ │ │ │ │ │ ├── alignment/ │ │ │ │ │ │ │ ├── alignment.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── alignment.karma.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── alignment.js │ │ │ │ │ │ │ │ └── useAlignment.js │ │ │ │ │ │ │ └── useAlignment.js │ │ │ │ │ │ ├── animation/ │ │ │ │ │ │ │ ├── animation.js │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ ├── directionRadioInput.js │ │ │ │ │ │ │ ├── effectChooserDropdown/ │ │ │ │ │ │ │ │ ├── dropdownConstants.js │ │ │ │ │ │ │ │ ├── dropdownItem.js │ │ │ │ │ │ │ │ ├── effectChooserDropdown.js │ │ │ │ │ │ │ │ ├── effectChooserElements.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ │ │ ├── types.js │ │ │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ │ │ ├── generateDynamicProps.js │ │ │ │ │ │ │ │ ├── getDisabledBackgroundEffects.js │ │ │ │ │ │ │ │ ├── hasDynamicProperty.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── updateDynamicProps.js │ │ │ │ │ │ │ ├── effectInput.js │ │ │ │ │ │ │ ├── effectPanel.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── animation.karma.js │ │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ │ ├── directionRadioInput.js │ │ │ │ │ │ │ │ └── effectChooser.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ ├── directionRadioInput.js │ │ │ │ │ │ │ └── effectInput.js │ │ │ │ │ │ ├── audioSticker/ │ │ │ │ │ │ │ ├── audioStickerStyle.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── stickerSize.js │ │ │ │ │ │ │ ├── stickerStyle.js │ │ │ │ │ │ │ ├── stickerType.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── stickerSize.js │ │ │ │ │ │ │ │ ├── stickerStyle.js │ │ │ │ │ │ │ │ └── stickerType.js │ │ │ │ │ │ │ └── utils.js │ │ │ │ │ │ ├── border/ │ │ │ │ │ │ │ ├── border.js │ │ │ │ │ │ │ ├── borderWidth.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── border.karma.js │ │ │ │ │ │ │ └── shared.js │ │ │ │ │ │ ├── captions/ │ │ │ │ │ │ │ ├── captions.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── captions.js │ │ │ │ │ │ ├── filter/ │ │ │ │ │ │ │ ├── convertOverlay.js │ │ │ │ │ │ │ ├── filter.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── filter.karma.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── convertOverlay.js │ │ │ │ │ │ ├── imageAccessibility/ │ │ │ │ │ │ │ ├── imageAccessibility.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── imageAccessibility.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── link/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── link.karma.js │ │ │ │ │ │ │ ├── link.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── link.js │ │ │ │ │ │ ├── pageAdvancement/ │ │ │ │ │ │ │ ├── customPageAdvancement.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── pageAttachment/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── outlink.js │ │ │ │ │ │ │ ├── pageAttachment.js │ │ │ │ │ │ │ ├── shared.js │ │ │ │ │ │ │ └── shoppingAttachment.js │ │ │ │ │ │ ├── pageBackground/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── pageBackground.karma.js │ │ │ │ │ │ │ ├── pageBackground.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── pageBackground.js │ │ │ │ │ │ ├── pageBackgroundAudio/ │ │ │ │ │ │ │ ├── backgroundAudio.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── pageBackgroundAudio.karma.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── backgroundAudio.js │ │ │ │ │ │ ├── product/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── product.js │ │ │ │ │ │ ├── shapeStyle/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── shapeStyle.js │ │ │ │ │ │ ├── sizePosition/ │ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ ├── borderRadius.karma.js │ │ │ │ │ │ │ │ └── sizePosition.karma.js │ │ │ │ │ │ │ ├── opacity.js │ │ │ │ │ │ │ ├── radius.js │ │ │ │ │ │ │ ├── sizePosition.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── sizePosition.js │ │ │ │ │ │ │ ├── usePresubmitHandlers.js │ │ │ │ │ │ │ └── utils.js │ │ │ │ │ │ ├── textAccessibility/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── textAccessibility.js │ │ │ │ │ │ │ └── textAccessibility.js │ │ │ │ │ │ ├── textStyle/ │ │ │ │ │ │ │ ├── backgroundColor.js │ │ │ │ │ │ │ ├── color.js │ │ │ │ │ │ │ ├── font.js │ │ │ │ │ │ │ ├── getClosestFontWeight.js │ │ │ │ │ │ │ ├── getFontWeights.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ ├── contrast.karma.js │ │ │ │ │ │ │ │ ├── stylePresets.karma.js │ │ │ │ │ │ │ │ └── textStyle.other.karma.js │ │ │ │ │ │ │ ├── padding.js │ │ │ │ │ │ │ ├── panelHeader.js │ │ │ │ │ │ │ ├── style.js │ │ │ │ │ │ │ ├── stylePresets.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ ├── fontPicker.js │ │ │ │ │ │ │ │ ├── fontsResponse.json │ │ │ │ │ │ │ │ ├── getClosestFontWeight.js │ │ │ │ │ │ │ │ ├── getFontWeights.js │ │ │ │ │ │ │ │ ├── stylePresetPanel.js │ │ │ │ │ │ │ │ ├── textBox.js │ │ │ │ │ │ │ │ └── textStyle.js │ │ │ │ │ │ │ ├── textStyle.js │ │ │ │ │ │ │ ├── useRichTextFormatting.js │ │ │ │ │ │ │ └── utils.js │ │ │ │ │ │ ├── videoAccessibility/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── videoPoster.karma.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── videoAccessibility.js │ │ │ │ │ │ │ └── videoAccessibility.js │ │ │ │ │ │ ├── videoOptions/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ │ └── videoOptions.karma.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── videoOptions.js │ │ │ │ │ │ │ └── videoOptions.js │ │ │ │ │ │ ├── videoSegment/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── videoSegment.js │ │ │ │ │ │ └── warning/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── warning.js │ │ │ │ │ ├── document/ │ │ │ │ │ │ ├── backgroundAudio/ │ │ │ │ │ │ │ ├── backgroundAudio.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── backgroundAudio.js │ │ │ │ │ │ ├── excerpt/ │ │ │ │ │ │ │ ├── excerpt.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── excerpt.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── pageAdvancement/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── pageAdvancement.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── pageAdvancement.js │ │ │ │ │ │ ├── slug/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── slug.js │ │ │ │ │ │ │ └── test/ │ │ │ │ │ │ │ └── slug.js │ │ │ │ │ │ └── taxonomies/ │ │ │ │ │ │ ├── FlatTermSelector.js │ │ │ │ │ │ ├── HierarchicalTermSelector.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ └── taxonomies.karma.js │ │ │ │ │ │ ├── shared.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── taxonomies.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── taxonomies.js │ │ │ │ │ ├── layer/ │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── elementLayer.js │ │ │ │ │ │ ├── elementLayerActions.js │ │ │ │ │ │ ├── groupLayer.js │ │ │ │ │ │ ├── groupLayerActions.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── karma/ │ │ │ │ │ │ │ └── layer.karma.js │ │ │ │ │ │ ├── layer.js │ │ │ │ │ │ ├── layerAction.js │ │ │ │ │ │ ├── layerComponents.js │ │ │ │ │ │ ├── layerForm.js │ │ │ │ │ │ ├── layerIdContext.js │ │ │ │ │ │ ├── layerList.js │ │ │ │ │ │ ├── layerPanel.js │ │ │ │ │ │ ├── reorderableElementLayer.js │ │ │ │ │ │ ├── reorderableGroupLayer.js │ │ │ │ │ │ ├── reorderableLayer.js │ │ │ │ │ │ ├── shapeMaskWrapper.js │ │ │ │ │ │ ├── useGroupSelection.js │ │ │ │ │ │ ├── useLayerSelection.js │ │ │ │ │ │ └── useLayers.js │ │ │ │ │ ├── panel/ │ │ │ │ │ │ ├── context.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── panel.js │ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ │ ├── content.js │ │ │ │ │ │ │ ├── handle.js │ │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ │ └── handle.js │ │ │ │ │ │ │ └── title.js │ │ │ │ │ │ ├── simplePanel.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── simplePanel.js │ │ │ │ │ │ ├── useDragHandlers.js │ │ │ │ │ │ └── useKeyboardHandlers.js │ │ │ │ │ ├── shared/ │ │ │ │ │ │ ├── flipControls.js │ │ │ │ │ │ ├── generalPageAdvancement.js │ │ │ │ │ │ ├── getCommonObjectValue.js │ │ │ │ │ │ ├── getCommonValue.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── linkRelations.js │ │ │ │ │ │ ├── media/ │ │ │ │ │ │ │ ├── audioPlayer.js │ │ │ │ │ │ │ ├── backgroundAudioPanelContent.js │ │ │ │ │ │ │ ├── captionsPanelContent.js │ │ │ │ │ │ │ ├── dropDownMenu.js │ │ │ │ │ │ │ ├── fileRow.js │ │ │ │ │ │ │ └── loopPanelContent.js │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ ├── _utils.js │ │ │ │ │ │ │ ├── getCommonObjectValue.js │ │ │ │ │ │ │ └── linkRelations.js │ │ │ │ │ │ ├── useCommonColorValue.js │ │ │ │ │ │ └── useCommonObjectValue.js │ │ │ │ │ └── utils/ │ │ │ │ │ ├── dropDownKeyEvents.js │ │ │ │ │ ├── metricsForTextPadding.js │ │ │ │ │ └── test/ │ │ │ │ │ └── metricsForTextPadding.js │ │ │ │ ├── previewPage/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── previewErrorBoundary.js │ │ │ │ │ ├── previewPage.js │ │ │ │ │ └── previewPageElements.js │ │ │ │ ├── publishModal/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── content/ │ │ │ │ │ │ ├── checklistButton.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── mainStoryInfo.js │ │ │ │ │ │ └── storyPreview.js │ │ │ │ │ ├── header/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── publishModal.karma.js │ │ │ │ │ ├── publishModal.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── content.js │ │ │ │ │ ├── header.js │ │ │ │ │ ├── mainStoryInfo.js │ │ │ │ │ └── storyPreview.js │ │ │ │ ├── reorderable/ │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── reorderable.js │ │ │ │ │ ├── reorderableItem.js │ │ │ │ │ ├── reorderableScroller.js │ │ │ │ │ ├── reorderableSeparator.js │ │ │ │ │ ├── useReorderable.js │ │ │ │ │ ├── useReordering.js │ │ │ │ │ └── useScroll.js │ │ │ │ ├── secondaryPopup/ │ │ │ │ │ ├── components.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── navigationWrapper.js │ │ │ │ │ ├── topNavigation.js │ │ │ │ │ └── utils.js │ │ │ │ ├── shopping/ │ │ │ │ │ └── frame.js │ │ │ │ ├── sidebar/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── context.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── karma/ │ │ │ │ │ │ └── sidebarTabs.karma.js │ │ │ │ │ ├── sidebar.js │ │ │ │ │ ├── sidebarContent.js │ │ │ │ │ ├── sidebarLayout.js │ │ │ │ │ ├── sidebarProvider.js │ │ │ │ │ ├── useSidebar.js │ │ │ │ │ └── utils.js │ │ │ │ ├── storyFontPicker/ │ │ │ │ │ └── index.js │ │ │ │ ├── style/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── context.js │ │ │ │ │ ├── designPanel.js │ │ │ │ │ ├── getDesignPanelsForSelection.js │ │ │ │ │ ├── icons/ │ │ │ │ │ │ ├── animationIcon.js │ │ │ │ │ │ ├── audioStickerSelectionIcon.js │ │ │ │ │ │ ├── imageSelectionIcon.js │ │ │ │ │ │ ├── linkIcon.js │ │ │ │ │ │ ├── multiSelectionIcon.js │ │ │ │ │ │ ├── productSelectionIcon.js │ │ │ │ │ │ ├── selectionIcon.js │ │ │ │ │ │ ├── shapeSelectionIcon.js │ │ │ │ │ │ ├── textSelectionIcon.js │ │ │ │ │ │ └── videoSelectionIcon.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── style.js │ │ │ │ │ ├── styleLayout.js │ │ │ │ │ ├── stylePanes.js │ │ │ │ │ ├── styleProvider.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── designPanel.js │ │ │ │ │ │ └── updateProperties.js │ │ │ │ │ ├── updateProperties.js │ │ │ │ │ ├── useDesignPanels.js │ │ │ │ │ └── useStyle.js │ │ │ │ ├── styleManager/ │ │ │ │ │ ├── components.js │ │ │ │ │ ├── confirmationDialog.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── header.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── confirmationDialog.js │ │ │ │ │ ├── styleGroup.js │ │ │ │ │ ├── styleItem.js │ │ │ │ │ ├── styleManager.js │ │ │ │ │ ├── useApplyStyle.js │ │ │ │ │ ├── useDeleteStyle.js │ │ │ │ │ └── useKeyboardNavigation.js │ │ │ │ ├── tablist/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ └── tablistPanel.js │ │ │ │ ├── tabview/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── thumbnail/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── LayerThumbnail.js │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── overflowThumbnail.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ ├── demoThumbnails.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ └── thumbnail.js │ │ │ │ ├── toggleButton/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── stories/ │ │ │ │ │ └── index.js │ │ │ │ ├── tooltip/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── tooltip.js │ │ │ │ ├── transition/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── scheduledTransition.js │ │ │ │ ├── uploadDropTarget/ │ │ │ │ │ ├── context.js │ │ │ │ │ ├── dropTarget.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── message.js │ │ │ │ │ ├── overlay.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── dropTarget.js │ │ │ │ │ └── use.js │ │ │ │ ├── videoTrim/ │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── currentTime.js │ │ │ │ │ ├── generateVideoStrip.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── provider.js │ │ │ │ │ ├── recordingProvider.js │ │ │ │ │ ├── slider.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── useVideoNode.js │ │ │ │ │ │ ├── useVideoTrimMode.js │ │ │ │ │ │ └── videoTrimmer.js │ │ │ │ │ ├── trimmerComponents.js │ │ │ │ │ ├── useRailBackground.js │ │ │ │ │ ├── useVideoNode.js │ │ │ │ │ ├── useVideoTrim.js │ │ │ │ │ ├── useVideoTrimMode.js │ │ │ │ │ ├── videoTrimContext.js │ │ │ │ │ └── videoTrimmer.js │ │ │ │ └── workspace/ │ │ │ │ ├── index.js │ │ │ │ └── layout.js │ │ │ ├── constants/ │ │ │ │ ├── audioSticker.ts │ │ │ │ ├── fonts.ts │ │ │ │ ├── headings.ts │ │ │ │ ├── index.ts │ │ │ │ ├── media.ts │ │ │ │ ├── multipleValue.ts │ │ │ │ ├── performanceTrackingEvents.ts │ │ │ │ └── zIndex.ts │ │ │ ├── dataUtils/ │ │ │ │ └── formattedTemplatesArray.js │ │ │ ├── getDefaultConfig.js │ │ │ ├── icons/ │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── karma/ │ │ │ │ ├── copyAndPaste.cuj.karma.js │ │ │ │ ├── duplicate.cuj.karma.js │ │ │ │ ├── element-library/ │ │ │ │ │ ├── audio-sticker/ │ │ │ │ │ │ └── audioSticker.karma.js │ │ │ │ │ ├── image/ │ │ │ │ │ │ ├── edit.karma.js │ │ │ │ │ │ └── resourceLoading.karma.js │ │ │ │ │ ├── text/ │ │ │ │ │ │ ├── edit.karma.js │ │ │ │ │ │ └── frame.karma.js │ │ │ │ │ └── video/ │ │ │ │ │ ├── autoplay.karma.js │ │ │ │ │ └── elementMinSizeAndPlayback.karma.js │ │ │ │ ├── elementTransform.cuj.karma.js │ │ │ │ ├── fixture/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── checklist/ │ │ │ │ │ │ │ ├── accessibility/ │ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ │ ├── design/ │ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── priority/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── documentPane/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── header/ │ │ │ │ │ │ ├── buttons/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── containers/ │ │ │ │ │ │ ├── canvas.js │ │ │ │ │ │ ├── carousel.js │ │ │ │ │ │ ├── checklist.js │ │ │ │ │ │ ├── common/ │ │ │ │ │ │ │ ├── color.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── radio.js │ │ │ │ │ │ │ ├── select.js │ │ │ │ │ │ │ ├── toggle.js │ │ │ │ │ │ │ └── toggleButton.js │ │ │ │ │ │ ├── container.js │ │ │ │ │ │ ├── designMenu.js │ │ │ │ │ │ ├── designPanel/ │ │ │ │ │ │ │ ├── abstractPanel.js │ │ │ │ │ │ │ ├── alignment.js │ │ │ │ │ │ │ ├── animationPanel.js │ │ │ │ │ │ │ ├── audioStickerSize.js │ │ │ │ │ │ │ ├── audioStickerStyle.js │ │ │ │ │ │ │ ├── audioStickerType.js │ │ │ │ │ │ │ ├── border.js │ │ │ │ │ │ │ ├── captions.js │ │ │ │ │ │ │ ├── colorPreset.js │ │ │ │ │ │ │ ├── filter.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── layers.js │ │ │ │ │ │ │ ├── link.js │ │ │ │ │ │ │ ├── pageBackground.js │ │ │ │ │ │ │ ├── pageBackgroundAudio.js │ │ │ │ │ │ │ ├── shapeStyle.js │ │ │ │ │ │ │ ├── sizePosition.js │ │ │ │ │ │ │ ├── textStyle.js │ │ │ │ │ │ │ ├── videoOptions.js │ │ │ │ │ │ │ └── videoPoster.js │ │ │ │ │ │ ├── documentPanel/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── taxonomies.js │ │ │ │ │ │ ├── editor.js │ │ │ │ │ │ ├── footer.js │ │ │ │ │ │ ├── gridView.js │ │ │ │ │ │ ├── header.js │ │ │ │ │ │ ├── helpCenter.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── keyboardShortcuts.js │ │ │ │ │ │ ├── library/ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── pageTemplates.js │ │ │ │ │ │ │ └── text.js │ │ │ │ │ │ ├── quickActionMenu.js │ │ │ │ │ │ └── sidebar.js │ │ │ │ │ ├── db/ │ │ │ │ │ │ ├── getMediaResponse.js │ │ │ │ │ │ ├── getProductsResponse.js │ │ │ │ │ │ ├── getTaxonomiesResponse.js │ │ │ │ │ │ ├── getTaxonomyTermResponse.js │ │ │ │ │ │ ├── singleSavedTemplate.js │ │ │ │ │ │ └── storyResponse.js │ │ │ │ │ ├── fixture.js │ │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ ├── integrationLayerTesting/ │ │ │ │ │ ├── config.karma.js │ │ │ │ │ └── optionalCallbacks.karma.js │ │ │ │ ├── media.cuj.karma.js │ │ │ │ ├── richText/ │ │ │ │ │ ├── _utils.js │ │ │ │ │ ├── inlineSelection.karma.js │ │ │ │ │ ├── inlineStyleOverride.karma.js │ │ │ │ │ ├── multiSelection.karma.js │ │ │ │ │ └── singleSelection.karma.js │ │ │ │ └── text.cuj.karma.js │ │ │ ├── propTypes.js │ │ │ ├── storyEditor.js │ │ │ ├── theme.js │ │ │ ├── types/ │ │ │ │ ├── apiProvider.ts │ │ │ │ ├── canvasProvider.ts │ │ │ │ ├── configProvider.ts │ │ │ │ ├── currentUserProvider.ts │ │ │ │ ├── highlightsProvider.ts │ │ │ │ ├── historyProvider.ts │ │ │ │ ├── index.ts │ │ │ │ ├── layoutProvider.ts │ │ │ │ ├── pageCanvas.ts │ │ │ │ ├── pageDataUrls.ts │ │ │ │ ├── story.ts │ │ │ │ ├── storyEditor.ts │ │ │ │ ├── storyProvider.ts │ │ │ │ ├── storyTriggers.ts │ │ │ │ └── taxonomyProvider.ts │ │ │ ├── typings/ │ │ │ │ ├── apcx-hues.d.ts │ │ │ │ ├── colorthief.d.ts │ │ │ │ ├── dom.d.ts │ │ │ │ ├── global.d.ts │ │ │ │ ├── libheif-js.d.ts │ │ │ │ └── svg.d.ts │ │ │ └── utils/ │ │ │ ├── __mocks__/ │ │ │ │ └── getBlurHashFromImage.js │ │ │ ├── cleanForSlug.ts │ │ │ ├── contrastUtils.ts │ │ │ ├── copyPaste.tsx │ │ │ ├── createError.ts │ │ │ ├── createThumbnailCanvasFromFullbleedCanvas.ts │ │ │ ├── dragEvent.ts │ │ │ ├── generateBlurhash.worker.js │ │ │ ├── generateGroupName.ts │ │ │ ├── getBlurHashFromImage.js │ │ │ ├── getCropParams.ts │ │ │ ├── getInUseFonts.ts │ │ │ ├── getInsertedElementSize.ts │ │ │ ├── getMediaBaseColor.ts │ │ │ ├── getSessionStorageKey.ts │ │ │ ├── getUniquePresets.ts │ │ │ ├── getUpdatedSizeAndPosition.js │ │ │ ├── idleCallback.ts │ │ │ ├── isDefaultPage.ts │ │ │ ├── isOffCanvas.ts │ │ │ ├── isTargetOutOfContainer.ts │ │ │ ├── keyboardOnlyOutline.js │ │ │ ├── nativeCopyPasteExpected.ts │ │ │ ├── noop.ts │ │ │ ├── objectPick.ts │ │ │ ├── objectWithout.ts │ │ │ ├── presetUtils.js │ │ │ ├── removeDupsFromArray.ts │ │ │ ├── storyUpdates.ts │ │ │ ├── test/ │ │ │ │ ├── cleanForSlug.js │ │ │ │ ├── contrastUtils.js │ │ │ │ ├── copyPaste.js │ │ │ │ ├── createError.js │ │ │ │ ├── generateGroupName.js │ │ │ │ ├── getCropParams.js │ │ │ │ ├── getInUseFonts.js │ │ │ │ ├── getInsertedElementSize.js │ │ │ │ ├── getUniquePresets.js │ │ │ │ ├── isDefaultPage.js │ │ │ │ ├── isOffCanvas.js │ │ │ │ ├── nativeCopyPasteExpected.js │ │ │ │ ├── objectPick.js │ │ │ │ ├── presetUtils.js │ │ │ │ ├── removeDupsFromArray.js │ │ │ │ ├── storyUpdates.js │ │ │ │ ├── textMeasurements.js │ │ │ │ ├── useElementsWithLinks.js │ │ │ │ ├── useGlobalClipboardHandlers.js │ │ │ │ ├── useHandlers.js │ │ │ │ ├── useIdleTaskQueue.js │ │ │ │ ├── useIsUploadingToStory.js │ │ │ │ ├── usePreventWindowUnload.js │ │ │ │ └── useRovingTabIndex.js │ │ │ ├── useAddPreset.js │ │ │ ├── useApplyTextAutoStyle.js │ │ │ ├── useCORSProxy.ts │ │ │ ├── useDoubleClick.ts │ │ │ ├── useElementPolygon.js │ │ │ ├── useElementsWithLinks.ts │ │ │ ├── useFocusTrapping.js │ │ │ ├── useGlobalClipboardHandlers.ts │ │ │ ├── useHandlers.ts │ │ │ ├── useIdleTaskQueue.ts │ │ │ ├── useIsUploadingToStory.js │ │ │ ├── usePerformanceTracking.ts │ │ │ ├── usePreventWindowUnload.ts │ │ │ ├── useRefreshPostEditURL.ts │ │ │ ├── useRovingTabIndex/ │ │ │ │ ├── flatNavigation.js │ │ │ │ ├── index.js │ │ │ │ └── nestedNavigation.js │ │ │ ├── useShapeMask.js │ │ │ └── useShapeMaskElements.js │ │ └── tsconfig.json │ ├── templates/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── cli.js │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── getMetaData.ts │ │ │ ├── getTemplates.ts │ │ │ ├── index.ts │ │ │ ├── raw/ │ │ │ │ ├── 12-hours-in-barcelona/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── a-day-in-the-life/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── ace-hotel-kyoto-review/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── album-releases/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── all-about-cars/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── almodos-films/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── an-artists-legacy/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── art-books-gift-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── baking-bread-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── beauty-quiz/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── belly-fat-workout/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── buying-art-on-the-internet/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── celebrity-life-story/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── celebrity-q-and-a/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── diy-home-office/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── doers-get-more-done/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── elegant-travel-itinerary/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── experience-thailand/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── fashion-inspiration/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── fashion-on-the-go/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── fitness-apps-ranked/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── food-and-stuff/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── fresh-and-bright/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── google-music-studio-tour/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── hawaii-travel-packing-list/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── honeymooning-in-italy/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── house-hunting/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── how-contact-tracing-works/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── how-video-calls-saved-the-day/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── indoor-garden-oasis/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── kitchen-makeover/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── kitchen-stories/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── laptop-buying-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── los-angeles-city-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── magazine-article/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── modernist-travel-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── new-york-party-round-up/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── no-days-off/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── one-day-city-itinerary/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── pizzas-in-nyc/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── plant-based-dyes/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── pride-month-watchlist/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── rock-music-festival/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── sangria-artichoke/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── self-care-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── series-best-of/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── simple-tech-tutorial/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── skin-care-at-home/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── sleep/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── sports-quiz/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── street-style-on-the-go/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── summer-adventure-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── summer-fashion-collection/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── sustainability-tips/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── technology-advice/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── tips-for-throwing-an-outdoor-luau/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── tv-show-recap/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── ultimate-comparison/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── vintage-chairs-buying-guide/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ ├── ways-to-eat-avocado/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── metaData.ts │ │ │ │ │ ├── template.d.ts │ │ │ │ │ └── template.json │ │ │ │ └── weekly-entertainment/ │ │ │ │ ├── index.ts │ │ │ │ ├── metaData.ts │ │ │ │ ├── template.d.ts │ │ │ │ └── template.json │ │ │ ├── test/ │ │ │ │ ├── getTemplates.js │ │ │ │ └── raw.js │ │ │ ├── types.ts │ │ │ └── utils/ │ │ │ ├── memoize.ts │ │ │ └── test/ │ │ │ └── memoize.js │ │ └── tsconfig.json │ ├── test-utils/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── firePointerEvent.ts │ │ │ ├── index.ts │ │ │ ├── queryByAriaLabel.ts │ │ │ ├── queryByAutoAdvanceAfter.ts │ │ │ ├── queryById.ts │ │ │ ├── renderWithTheme.tsx │ │ │ └── typings/ │ │ │ └── svg.d.ts │ │ └── tsconfig.json │ ├── text-sets/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── cli.js │ │ ├── src/ │ │ │ ├── index.ts │ │ │ ├── loadTextSets.ts │ │ │ ├── raw/ │ │ │ │ ├── contact.json │ │ │ │ ├── cover.json │ │ │ │ ├── editorial.json │ │ │ │ ├── list.json │ │ │ │ ├── quote.json │ │ │ │ ├── section_header.json │ │ │ │ ├── step.json │ │ │ │ └── table.json │ │ │ ├── test/ │ │ │ │ └── raw.js │ │ │ └── types.ts │ │ └── tsconfig.json │ ├── tinymce-button/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── components/ │ │ │ ├── Modal.js │ │ │ ├── controls/ │ │ │ │ ├── Toggle.js │ │ │ │ └── test/ │ │ │ │ └── Toggle.js │ │ │ └── test/ │ │ │ └── Modal.js │ │ ├── containers/ │ │ │ └── Modal.js │ │ ├── index.js │ │ ├── store/ │ │ │ ├── actions.js │ │ │ ├── default.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ ├── selectors.js │ │ │ └── test/ │ │ │ ├── actions.js │ │ │ └── selectors.js │ │ └── utils/ │ │ ├── index.js │ │ └── test/ │ │ └── index.js │ ├── tracking/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── disableTracking.ts │ │ │ ├── enableTracking.ts │ │ │ ├── getTimeTracker.ts │ │ │ ├── index.ts │ │ │ ├── initializeErrorReporting.ts │ │ │ ├── initializeTracking.ts │ │ │ ├── isTrackingEnabled.ts │ │ │ ├── shared.ts │ │ │ ├── test/ │ │ │ │ ├── disableTracking.ts │ │ │ │ ├── enableTracking.ts │ │ │ │ ├── getTimeTracker.ts │ │ │ │ ├── gtag.ts │ │ │ │ ├── initializeTracking.ts │ │ │ │ ├── isTrackingEnabled.ts │ │ │ │ ├── trackError.ts │ │ │ │ ├── trackEvent.ts │ │ │ │ ├── trackScreenView.ts │ │ │ │ └── trackTiming.ts │ │ │ ├── track.ts │ │ │ ├── trackClick.ts │ │ │ ├── trackError.ts │ │ │ ├── trackEvent.ts │ │ │ ├── trackScreenView.ts │ │ │ └── trackTiming.ts │ │ └── tsconfig.json │ ├── transform/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── context.ts │ │ │ ├── index.ts │ │ │ ├── transformProvider.tsx │ │ │ ├── types.ts │ │ │ ├── useTransform.ts │ │ │ └── useTransformHandler.ts │ │ └── tsconfig.json │ ├── units/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── calcRotatedObjectPositionAndSize.ts │ │ │ ├── calcRotatedResizeOffset.ts │ │ │ ├── constants.ts │ │ │ ├── context.ts │ │ │ ├── dimensions.ts │ │ │ ├── getBoundRect.ts │ │ │ ├── getCorner.ts │ │ │ ├── getCorners.ts │ │ │ ├── index.ts │ │ │ ├── range.ts │ │ │ ├── test/ │ │ │ │ ├── getBoundRect.ts │ │ │ │ └── range.ts │ │ │ ├── types.ts │ │ │ ├── unitsProvider.tsx │ │ │ └── useUnits.ts │ │ └── tsconfig.json │ ├── url/ │ │ ├── .npmignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── addQueryArgs.ts │ │ │ ├── index.ts │ │ │ ├── safeDecodeUriComponent.ts │ │ │ ├── test/ │ │ │ │ ├── addQueryArgs.ts │ │ │ │ ├── safeDecodeUriComponent.js │ │ │ │ └── url.ts │ │ │ └── url.ts │ │ └── tsconfig.json │ ├── widget/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── index.js │ │ └── style.css │ ├── wp-dashboard/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── api/ │ │ │ ├── authors.js │ │ │ ├── constants/ │ │ │ │ └── index.js │ │ │ ├── fonts.js │ │ │ ├── hooks/ │ │ │ │ ├── useApiAlerts.js │ │ │ │ ├── useFontsApi.js │ │ │ │ ├── useMediaApi.js │ │ │ │ ├── usePagesApi.js │ │ │ │ ├── usePublisherLogosApi.js │ │ │ │ ├── useSettingsApi.js │ │ │ │ └── useUserApi.js │ │ │ ├── index.js │ │ │ ├── media.js │ │ │ ├── pages.js │ │ │ ├── publisherLogo.js │ │ │ ├── reducers/ │ │ │ │ ├── media.js │ │ │ │ ├── publisherLogos.js │ │ │ │ ├── settings.js │ │ │ │ └── test/ │ │ │ │ ├── media.js │ │ │ │ ├── publisherLogos.js │ │ │ │ └── settings.js │ │ │ ├── settings.js │ │ │ ├── shopping.js │ │ │ ├── story.js │ │ │ ├── taxonomies.js │ │ │ ├── test/ │ │ │ │ ├── editorSettingsApi.js │ │ │ │ └── user.js │ │ │ ├── user.js │ │ │ └── utils/ │ │ │ ├── index.js │ │ │ ├── reshapeStoryObject.js │ │ │ └── test/ │ │ │ └── reshapeStoryObject.js │ │ ├── components/ │ │ │ ├── editorSettings/ │ │ │ │ ├── adManagement/ │ │ │ │ │ ├── adNetwork/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── adNetwork.js │ │ │ │ │ ├── googleAdManager/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── googleAdManager.js │ │ │ │ │ ├── googleAdSense/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── googleAdSense.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mgid/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── stories/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── mgid.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── adManagement.js │ │ │ │ ├── archive/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── archive.js │ │ │ │ ├── components.js │ │ │ │ ├── context.js │ │ │ │ ├── customFonts/ │ │ │ │ │ ├── confirmationDialog.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── customFonts.js │ │ │ │ │ └── utils/ │ │ │ │ │ └── getFontDataFromUrl.js │ │ │ │ ├── dataRemoval/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── DataRemovalSettings.js │ │ │ │ ├── dataUtils/ │ │ │ │ │ ├── formattedCustomFonts.js │ │ │ │ │ └── formattedPublisherLogos.js │ │ │ │ ├── editorSettings.js │ │ │ │ ├── editorSettingsProvider.js │ │ │ │ ├── googleAnalytics/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── googleAnalytics.js │ │ │ │ ├── index.js │ │ │ │ ├── mediaOptimization/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── mediaOptimizationSettings.js │ │ │ │ ├── pageAdvancement/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── pageAdvancement.js │ │ │ │ ├── publisherLogo/ │ │ │ │ │ ├── gridItem.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── popoverLogoContextMenu.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── publisherLogo.js │ │ │ │ ├── shopping/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── shopify/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── shoppingProviderDropDown.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── shopping.js │ │ │ │ │ └── shoppingProvider.js │ │ │ │ ├── telemetry/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── stories/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── telemetrySettings.js │ │ │ │ ├── test/ │ │ │ │ │ └── editorSettings.js │ │ │ │ ├── useEditorSettings.js │ │ │ │ ├── utils/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── validateAdManagerSlotIdFormat.js │ │ │ │ │ │ ├── validateAdSensePublisherIdFormat.js │ │ │ │ │ │ ├── validateAdSenseSlotIdFormat.js │ │ │ │ │ │ ├── validateGoogleAnalyticsIdFormat.js │ │ │ │ │ │ ├── validateMgidWidgetIdFormat.js │ │ │ │ │ │ └── validateShopifyHost.js │ │ │ │ │ ├── validateAdManagerSlotIdFormat.js │ │ │ │ │ ├── validateAdSensePublisherIdFormat.js │ │ │ │ │ ├── validateAdSenseSlotIdFormat.js │ │ │ │ │ ├── validateGoogleAnalyticsIdFormat.js │ │ │ │ │ ├── validateMgidWidgetIdFormat.js │ │ │ │ │ └── validateShopifyHost.js │ │ │ │ └── videoCache/ │ │ │ │ ├── index.js │ │ │ │ ├── stories/ │ │ │ │ │ └── index.js │ │ │ │ └── test/ │ │ │ │ └── videoCache.js │ │ │ ├── ga4Banner/ │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── layout/ │ │ │ │ └── index.js │ │ │ ├── telemetryBanner/ │ │ │ │ ├── index.js │ │ │ │ ├── stories/ │ │ │ │ │ └── telemetryBanner.js │ │ │ │ └── test/ │ │ │ │ └── telemetryBanner.js │ │ │ └── updateBanner/ │ │ │ └── index.js │ │ ├── constants/ │ │ │ ├── index.js │ │ │ ├── settings.js │ │ │ ├── textConstants.js │ │ │ └── wpAdmin.js │ │ ├── effects/ │ │ │ ├── index.js │ │ │ ├── useMediaOptimization.js │ │ │ ├── useSyncAdminMenu.js │ │ │ └── useTelemetryOptIn.js │ │ ├── index.js │ │ ├── publicPath.js │ │ ├── setLocaleData.js │ │ ├── style.css │ │ ├── testUtils/ │ │ │ ├── index.js │ │ │ ├── mockEditorProvider.js │ │ │ └── renderWithProviders.js │ │ └── theme.js │ ├── wp-story-editor/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ ├── api/ │ │ │ ├── authors.js │ │ │ ├── constants/ │ │ │ │ └── index.js │ │ │ ├── fonts.js │ │ │ ├── hotlinkInfo.js │ │ │ ├── index.js │ │ │ ├── media.js │ │ │ ├── metaboxes.js │ │ │ ├── metadata.js │ │ │ ├── pageTemplate.js │ │ │ ├── proxy.js │ │ │ ├── publisherLogos.js │ │ │ ├── shopping.js │ │ │ ├── statusCheck.js │ │ │ ├── story.js │ │ │ ├── storyLock.js │ │ │ ├── taxonomy.js │ │ │ ├── test/ │ │ │ │ ├── _utils.js │ │ │ │ ├── fonts.js │ │ │ │ ├── media.js │ │ │ │ ├── metaboxes.js │ │ │ │ ├── pageTemplates.js │ │ │ │ ├── story.js │ │ │ │ └── user.js │ │ │ ├── user.js │ │ │ └── utils/ │ │ │ ├── base64Encode.js │ │ │ ├── flattenFormData.js │ │ │ ├── getResourceFromAttachment.js │ │ │ ├── index.js │ │ │ ├── normalizeResourceSizes.js │ │ │ ├── test/ │ │ │ │ ├── base64Encode.js │ │ │ │ ├── flatternFormData.js │ │ │ │ └── normalizeResourceSizes.js │ │ │ └── transformStoryResponse.js │ │ ├── components/ │ │ │ ├── checklist/ │ │ │ │ ├── accessibility/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── videoOptimizationCheckbox/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── index.js │ │ │ │ ├── design/ │ │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ └── priority/ │ │ │ │ ├── index.js │ │ │ │ └── storyMissingPublisherName.js │ │ │ ├── corsCheck/ │ │ │ │ ├── corsCheck.js │ │ │ │ ├── corsCheckFailed.js │ │ │ │ ├── index.js │ │ │ │ ├── stories/ │ │ │ │ │ └── corsCheckFailed.js │ │ │ │ └── test/ │ │ │ │ └── corsCheck.js │ │ │ ├── crossOriginIsolation/ │ │ │ │ └── index.js │ │ │ ├── documentPane/ │ │ │ │ ├── index.js │ │ │ │ ├── publish/ │ │ │ │ │ ├── author.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── publish.js │ │ │ │ │ ├── publishTime.js │ │ │ │ │ └── test/ │ │ │ │ │ └── publish.js │ │ │ │ └── status/ │ │ │ │ ├── index.js │ │ │ │ ├── status.js │ │ │ │ └── test/ │ │ │ │ └── status.js │ │ │ ├── fontCheck/ │ │ │ │ ├── fontCheckDialog.js │ │ │ │ ├── index.js │ │ │ │ └── test/ │ │ │ │ └── fontCheck.js │ │ │ ├── header/ │ │ │ │ ├── buttons/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── test/ │ │ │ │ │ └── buttons.js │ │ │ │ └── index.js │ │ │ ├── helpCenter/ │ │
Showing preview only (798K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (7873 symbols across 2415 files)
FILE: .storybook/stories/playground/story-editor/api/fonts.js
function getFonts (line 17) | async function getFonts(params) {
FILE: .storybook/stories/playground/story-editor/constants.js
constant LOCAL_STORAGE_CONTENT_KEY (line 16) | const LOCAL_STORAGE_CONTENT_KEY = 'web_stories_json_content';
constant LOCAL_STORAGE_PREVIEW_MARKUP_KEY (line 17) | const LOCAL_STORAGE_PREVIEW_MARKUP_KEY = 'web_stories_preview_markup';
FILE: .storybook/stories/playground/story-editor/getDummyMedia.js
function createDummyImageData (line 21) | function createDummyImageData({
function createDummyVideoData (line 119) | function createDummyVideoData({
function getDummyMedia (line 142) | function getDummyMedia() {
FILE: .storybook/stories/playground/story-editor/header/buttons/index.js
function Loading (line 55) | function Loading() {
function Buttons (line 63) | function Buttons() {
FILE: .storybook/stories/playground/story-editor/header/buttons/preview.js
function PreviewButton (line 30) | function PreviewButton() {
FILE: .storybook/stories/playground/story-editor/header/buttons/saveButton.js
function SaveButton (line 28) | function SaveButton() {
FILE: .storybook/stories/playground/story-editor/header/index.js
function HeaderLayout (line 47) | function HeaderLayout() {
FILE: .storybook/stories/playground/story-editor/preview.js
function Preview (line 32) | function Preview() {
FILE: __mocks__/node:fs.js
function __setMockFiles (line 33) | function __setMockFiles(newMockFiles) {
function readdirSync (line 48) | function readdirSync(directoryPath) {
function existsSync (line 52) | function existsSync(dirOrFile) {
function readFileSync (line 66) | function readFileSync(file) {
function writeFileSync (line 71) | function writeFileSync(file, content) {
function lstatSync (line 80) | function lstatSync(dirOrFile) {
function rmdirSync (line 87) | function rmdirSync(dirname) {
function unlinkSync (line 93) | function unlinkSync(file) {
FILE: includes/AMP/Canonical_Sanitizer.php
class Canonical_Sanitizer (line 54) | class Canonical_Sanitizer extends AMP_Base_Sanitizer {
method sanitize (line 60) | public function sanitize(): void {
FILE: includes/AMP/Integration/AMP_Story_Sanitizer.php
class AMP_Story_Sanitizer (line 43) | class AMP_Story_Sanitizer extends AMP_Base_Sanitizer {
method sanitize (line 51) | public function sanitize(): void {
FILE: includes/AMP/Meta_Sanitizer.php
class Meta_Sanitizer (line 47) | class Meta_Sanitizer extends AMP_Meta_Sanitizer {
method ensure_boilerplate_is_present (line 61) | protected function ensure_boilerplate_is_present(): void {
method get_boilerplate_stylesheets (line 120) | protected function get_boilerplate_stylesheets(): array {
FILE: includes/AMP/Optimization.php
class Optimization (line 57) | class Optimization {
method optimize_document (line 65) | public function optimize_document( Document $document ): void {
method get_optimizer (line 108) | private function get_optimizer(): TransformationEngine {
method get_optimizer_configuration (line 134) | private static function get_optimizer_configuration(): Configuration {
FILE: includes/AMP/Output_Buffer.php
class Output_Buffer (line 47) | class Output_Buffer extends Service_Base implements Conditional {
method __construct (line 84) | public function __construct( Sanitization $sanitization, Optimization ...
method register (line 95) | public function register(): void {
method get_registration_action (line 110) | public static function get_registration_action(): string {
method get_registration_action_priority (line 121) | public static function get_registration_action_priority(): int {
method is_needed (line 136) | public static function is_needed(): bool {
method start_output_buffering (line 157) | public function start_output_buffering(): void {
method is_output_buffering (line 176) | public function is_output_buffering(): bool {
method finish_output_buffering (line 190) | public function finish_output_buffering( string $response ): string {
method prepare_response (line 212) | public function prepare_response( string $response ): string {
method render_error_page (line 238) | private function render_error_page( Throwable $throwable ): string {
FILE: includes/AMP/Sanitization.php
class Sanitization (line 58) | class Sanitization {
method __construct (line 74) | public function __construct( Settings $settings ) {
method sanitize_document (line 85) | public function sanitize_document( Document $document ): void {
method validation_error_callback (line 104) | public function validation_error_callback( array $error, array $data =...
method ensure_required_markup (line 141) | protected function ensure_required_markup( Document $document, array $...
method get_extension_sources (line 363) | protected function get_extension_sources(): array {
method is_amp_dev_mode (line 393) | protected function is_amp_dev_mode(): bool {
method get_sanitizers (line 432) | protected function get_sanitizers(): array {
FILE: includes/AMP/Story_Sanitizer.php
class Story_Sanitizer (line 41) | class Story_Sanitizer extends AMP_Base_Sanitizer {
method sanitize (line 49) | public function sanitize(): void {
FILE: includes/AMP/Tag_And_Attribute_Sanitizer.php
class Tag_And_Attribute_Sanitizer (line 32) | class Tag_And_Attribute_Sanitizer extends AMP_Tag_And_Attribute_Sanitizer {
method __construct (line 41) | public function __construct( Document $dom, array $args = [] ) { // ph...
FILE: includes/AMP/Traits/Sanitization_Utils.php
type Sanitization_Utils (line 43) | trait Sanitization_Utils {
method transform_html_start_tag (line 51) | private function transform_html_start_tag( $document ): void {
method transform_a_tags (line 80) | private function transform_a_tags( $document ): void {
method use_semantic_heading_tags (line 156) | private function use_semantic_heading_tags( $document ): void {
method use_semantic_heading_tags_for_elements (line 191) | private function use_semantic_heading_tags_for_elements( DOMNodeList $...
method change_tag_name (line 243) | private function change_tag_name( DOMElement $node, string $tag_name )...
method sanitize_amp_story_page_outlink (line 295) | private function sanitize_amp_story_page_outlink( $document ): void {
method add_publisher_logo (line 325) | private function add_publisher_logo( $document, string $publisher_logo...
method add_publisher (line 360) | private function add_publisher( $document, string $publisher ): void {
method add_poster_images (line 385) | private function add_poster_images( $document, array $poster_images ):...
method deduplicate_inline_styles (line 420) | private function deduplicate_inline_styles( $document ): void {
method disable_first_page_animations (line 487) | private function disable_first_page_animations( $document ): void {
method add_video_cache (line 514) | private function add_video_cache( $document, bool $video_cache_enabled...
method is_blob_url (line 539) | private function is_blob_url( string $url ): bool {
method remove_blob_urls (line 550) | private function remove_blob_urls( $document ): void {
method sanitize_srcset (line 602) | private function sanitize_srcset( $document ): void {
method remove_page_template_placeholder_images (line 652) | private function remove_page_template_placeholder_images( $document ):...
method sanitize_title_and_meta_description (line 687) | private function sanitize_title_and_meta_description( $document, strin...
FILE: includes/AMP_Story_Player_Assets.php
class AMP_Story_Player_Assets (line 39) | class AMP_Story_Player_Assets implements Service, Registerable {
method register (line 50) | public function register(): void {
method register_style (line 62) | public function register_style( WP_Styles $wp_styles ): void {
method register_script (line 78) | public function register_script( WP_Scripts $wp_scripts ): void {
FILE: includes/AdSense.php
class AdSense (line 36) | class AdSense extends Service_Base implements HasRequirements {
method __construct (line 52) | public function __construct( Settings $settings ) {
method register (line 61) | public function register(): void {
method get_requirements (line 74) | public static function get_requirements(): array {
method print_adsense_tag (line 83) | public function print_adsense_tag(): void {
method get_publisher_id (line 113) | private function get_publisher_id(): string {
method get_slot_id (line 130) | private function get_slot_id(): string {
method is_enabled (line 144) | private function is_enabled(): bool {
FILE: includes/Ad_Manager.php
class Ad_Manager (line 36) | class Ad_Manager extends Service_Base implements HasRequirements {
method __construct (line 52) | public function __construct( Settings $settings ) {
method register (line 61) | public function register(): void {
method get_requirements (line 74) | public static function get_requirements(): array {
method print_ad_manager_tag (line 83) | public function print_ad_manager_tag(): void {
method get_slot_id (line 124) | private function get_slot_id(): string {
method is_enabled (line 138) | private function is_enabled(): bool {
FILE: includes/Admin/Activation_Notice.php
class Activation_Notice (line 43) | class Activation_Notice implements ServiceInterface, Registerable, Plugi...
method __construct (line 69) | public function __construct( Assets $assets ) {
method register (line 78) | public function register(): void {
method on_plugin_activation (line 91) | public function on_plugin_activation( bool $network_wide ): void {
method on_plugin_deactivation (line 102) | public function on_plugin_deactivation( bool $network_wide ): void {
method enqueue_assets (line 113) | public function enqueue_assets( string $hook_suffix ): void {
method render_notice (line 141) | public function render_notice(): void {
method on_plugin_uninstall (line 166) | public function on_plugin_uninstall(): void {
method get_script_settings (line 180) | protected function get_script_settings(): array {
method is_plugins_page (line 231) | protected function is_plugins_page( $hook_suffix ): bool {
method set_activation_flag (line 244) | protected function set_activation_flag( bool $network_wide = false ): ...
method get_activation_flag (line 262) | protected function get_activation_flag( bool $network_wide = false ): ...
method delete_activation_flag (line 280) | protected function delete_activation_flag( bool $network_wide = false ...
FILE: includes/Admin/Admin.php
class Admin (line 44) | class Admin extends Service_Base {
method __construct (line 66) | public function __construct( Settings $settings, Context $context ) {
method register (line 76) | public function register(): void {
method get_registration_action (line 90) | public static function get_registration_action(): string {
method admin_body_class (line 105) | public function admin_body_class( $class_name ) {
method prefill_post_content (line 138) | public function prefill_post_content( $content, ?WP_Post $post ) {
method prefill_post_title (line 221) | public function prefill_post_title( $title ) {
method media_states (line 263) | public function media_states( $media_states, WP_Post $post ) {
FILE: includes/Admin/Cross_Origin_Isolation.php
class Cross_Origin_Isolation (line 41) | class Cross_Origin_Isolation extends Service_Base implements HasRequirem...
method __construct (line 64) | public function __construct( Preferences $preferences, Context $contex...
method register (line 72) | public function register(): void {
method get_registration_action (line 92) | public static function get_registration_action(): string {
method get_registration_action_priority (line 103) | public static function get_registration_action_priority(): int {
method get_requirements (line 114) | public static function get_requirements(): array {
method admin_header (line 123) | public function admin_header(): void {
method style_loader_tag (line 142) | public function style_loader_tag( $tag, string $handle, string $href ) {
method script_loader_tag (line 156) | public function script_loader_tag( $tag, string $handle, string $src ) {
method get_avatar (line 177) | public function get_avatar( $avatar, $id_or_email, $size, $default_url...
method override_media_templates (line 186) | public function override_media_templates(): void {
method custom_print_media_templates (line 196) | public function custom_print_media_templates(): void {
method needs_isolation (line 229) | private function needs_isolation(): bool {
method replace_in_dom (line 258) | protected function replace_in_dom( string $html ): string { // phpcs:i...
method add_attribute (line 333) | protected function add_attribute( $html, string $attribute, $url ) {
FILE: includes/Admin/Customizer.php
class Customizer (line 83) | class Customizer extends Service_Base implements Conditional {
method __construct (line 131) | public function __construct(
method register (line 144) | public function register(): void {
method is_needed (line 155) | public static function is_needed(): bool {
method register_customizer_settings (line 170) | public function register_customizer_settings( WP_Customize_Manager $wp...
method validate_number_of_stories (line 505) | public function validate_number_of_stories( WP_Error $validity, int $v...
method validate_number_of_columns (line 522) | public function validate_number_of_columns( WP_Error $validity, int $v...
method render_stories (line 539) | public function render_stories(): string {
method get_stories_theme_support (line 589) | public function get_stories_theme_support(): array {
method get_view_type_choices (line 670) | private function get_view_type_choices( array $view_type ): array {
method is_option_enabled (line 688) | private function is_option_enabled( string $option_name ): bool {
method is_view_type (line 701) | private function is_view_type( string $view_type ): bool {
method parse_args (line 719) | private function parse_args( array $args, array $defaults = [] ): array {
FILE: includes/Admin/Dashboard.php
class Dashboard (line 51) | class Dashboard extends Service_Base {
method __construct (line 177) | public function __construct(
method register (line 212) | public function register(): void {
method get_hook_suffix (line 228) | public function get_hook_suffix( string $key ) {
method add_menu_page (line 237) | public function add_menu_page(): void {
method redirect_menu_page (line 296) | public function redirect_menu_page(): void {
method load_stories_dashboard (line 332) | public function load_stories_dashboard(): void {
method render (line 424) | public function render(): void {
method enqueue_assets (line 435) | public function enqueue_assets( string $hook_suffix ): void {
method get_dashboard_settings (line 464) | public function get_dashboard_settings(): array {
method display_link_to_dashboard (line 559) | public function display_link_to_dashboard(): void {
FILE: includes/Admin/Editor.php
class Editor (line 50) | class Editor extends Service_Base implements HasRequirements {
method __construct (line 171) | public function __construct(
method register (line 204) | public function register(): void {
method get_requirements (line 219) | public static function get_requirements(): array {
method replace_editor (line 234) | public function replace_editor( $replace, WP_Post $post ) {
method filter_use_block_editor_for_post_type (line 272) | public function filter_use_block_editor_for_post_type( $use_block_edit...
method admin_enqueue_scripts (line 287) | public function admin_enqueue_scripts( string $hook ): void {
method get_editor_settings (line 342) | public function get_editor_settings(): array {
method setup_lock (line 504) | protected function setup_lock( int $story_id ): void {
FILE: includes/Admin/Google_Fonts.php
class Google_Fonts (line 43) | class Google_Fonts implements Conditional, Service, Registerable {
method is_needed (line 56) | public static function is_needed(): bool {
method register (line 65) | public function register(): void {
method register_style (line 76) | public function register_style( WP_Styles $wp_styles ): void {
FILE: includes/Admin/Meta_Boxes.php
class Meta_Boxes (line 37) | class Meta_Boxes extends Service_Base {
method register (line 53) | public function register(): void {
method remove_meta_boxes (line 69) | public function remove_meta_boxes(): void {
method get_meta_box_url (line 113) | public function get_meta_box_url( int $story_id ): string {
method get_meta_boxes_per_location (line 139) | public function get_meta_boxes_per_location(): array {
FILE: includes/Admin/PluginActionLinks.php
class PluginActionLinks (line 39) | class PluginActionLinks extends Service_Base {
method register (line 45) | public function register(): void {
method get_registration_action (line 57) | public static function get_registration_action(): string {
method action_links (line 73) | public function action_links( $links ) {
FILE: includes/Admin/PluginRowMeta.php
class PluginRowMeta (line 38) | class PluginRowMeta extends Service_Base {
method register (line 45) | public function register(): void {
method get_registration_action (line 56) | public static function get_registration_action(): string {
method get_plugin_row_meta (line 74) | public function get_plugin_row_meta( $meta, string $plugin_file ) {
FILE: includes/Admin/Site_Health.php
class Site_Health (line 40) | class Site_Health extends Service_Base implements Conditional {
method __construct (line 56) | public function __construct( Experiments $experiments ) {
method is_needed (line 67) | public static function is_needed(): bool {
method get_registration_action (line 78) | public static function get_registration_action(): string {
method register (line 87) | public function register(): void {
method add_debug_information (line 105) | public function add_debug_information( $debugging_information ) {
method add_extensions (line 184) | public function add_extensions( $core_extensions ) {
method modify_test_result (line 235) | public function modify_test_result( $test_result ) {
method get_formatted_output (line 257) | protected function get_formatted_output( $value ): string {
FILE: includes/Admin/TinyMCE.php
class TinyMCE (line 41) | class TinyMCE extends Service_Base {
method __construct (line 77) | public function __construct( Assets $assets, Stories_Script_Data $stor...
method register (line 88) | public function register(): void {
method get_registration_action (line 109) | public static function get_registration_action(): string {
method tinymce_web_stories_button (line 125) | public function tinymce_web_stories_button( $buttons ) {
method web_stories_mce_plugin (line 146) | public function web_stories_mce_plugin( $plugins ) {
method register_assets (line 160) | public function register_assets(): void {
method script_loader_tag (line 181) | public function script_loader_tag( $tag, string $handle, string $src ) {
method enqueue_assets (line 200) | public function enqueue_assets(): void {
method web_stories_tinymce_root_element (line 211) | public function web_stories_tinymce_root_element(): void {
FILE: includes/Analytics.php
class Analytics (line 34) | class Analytics extends Service_Base {
method __construct (line 50) | public function __construct( Settings $settings ) {
method register (line 59) | public function register(): void {
method get_tracking_id (line 70) | public function get_tracking_id(): string {
method get_default_configuration (line 99) | public function get_default_configuration( string $tracking_id ): array {
method print_analytics_tag (line 242) | public function print_analytics_tag(): void {
method print_amp_analytics_tag (line 263) | private function print_amp_analytics_tag( string $tracking_id ): void {
method print_amp_story_auto_analytics_tag (line 280) | private function print_amp_story_auto_analytics_tag( string $tracking_...
FILE: includes/Assets.php
class Assets (line 42) | class Assets {
method get_base_path (line 64) | public function get_base_path( string $path ): string {
method get_base_url (line 75) | public function get_base_url( string $path ): string {
method get_asset_metadata (line 89) | public function get_asset_metadata( string $handle ): array {
method register_script_asset (line 124) | public function register_script_asset( string $script_handle, array $s...
method enqueue_script_asset (line 192) | public function enqueue_script_asset( string $script_handle, array $sc...
method register_style_asset (line 205) | public function register_style_asset( string $style_handle, array $sty...
method enqueue_style_asset (line 250) | public function enqueue_style_asset( string $style_handle, array $styl...
method register_style (line 275) | public function register_style( string $style_handle, $src, array $dep...
method register_script (line 303) | public function register_script( string $script_handle, $src, array $d...
method enqueue_style (line 342) | public function enqueue_style( string $style_handle, string $src = '',...
method enqueue_script (line 366) | public function enqueue_script( string $script_handle, string $src = '...
method enqueue_script_module (line 381) | public function enqueue_script_module( string $script_handle, string $...
method remove_admin_style (line 399) | public function remove_admin_style( array $styles ): void {
method get_translations (line 411) | public function get_translations( string $script_handle ): array {
FILE: includes/Block/Web_Stories_Block.php
class Web_Stories_Block (line 90) | class Web_Stories_Block extends Embed_Base {
method __construct (line 134) | public function __construct(
method register (line 151) | public function register(): void {
method render_block (line 177) | public function render_block( array $attributes, string $content, WP_B...
method get_mapped_field_states (line 230) | public function get_mapped_field_states(): array {
method register_block_type (line 256) | protected function register_block_type(): void {
method get_script_settings (line 348) | private function get_script_settings(): array {
method initialize_block_attributes (line 380) | protected function initialize_block_attributes( array $block_attribute...
method get_query_args (line 397) | protected function get_query_args(): array {
FILE: includes/Context.php
class Context (line 34) | class Context {
method __construct (line 49) | public function __construct( Story_Post_Type $story_post_type ) {
method is_web_story (line 60) | public function is_web_story(): bool {
method is_amp (line 71) | public function is_amp(): bool {
method is_story_editor (line 95) | public function is_story_editor(): bool {
method is_upload_screen (line 108) | public function is_upload_screen(): bool {
method is_block_editor (line 119) | public function is_block_editor(): bool {
method get_screen_base (line 132) | public function get_screen_base(): ?string {
method get_screen_post_type (line 145) | public function get_screen_post_type(): ?string {
FILE: includes/Database_Upgrader.php
class Database_Upgrader (line 43) | class Database_Upgrader implements Service, Registerable, PluginActivati...
method __construct (line 95) | public function __construct( Injector $injector ) {
method register (line 104) | public function register(): void {
method on_plugin_activation (line 115) | public function on_plugin_activation( bool $network_wide ): void {
method on_site_initialization (line 126) | public function on_site_initialization( WP_Site $site ): void {
method run_upgrades (line 135) | public function run_upgrades(): void {
method on_plugin_uninstall (line 162) | public function on_plugin_uninstall(): void {
method run_upgrade_routine (line 176) | protected function run_upgrade_routine( string $class_name, string $ve...
method finish_up (line 195) | protected function finish_up( string $previous_version ): void {
FILE: includes/Decoder.php
class Decoder (line 36) | class Decoder {
method supports_decoding (line 44) | public function supports_decoding(): bool {
method base64_decode (line 63) | public function base64_decode( string $content ): string {
FILE: includes/Demo_Content.php
class Demo_Content (line 36) | class Demo_Content {
method get_title (line 40) | public function get_title(): string {
method get_content (line 47) | public function get_content(): string {
method update_assets_urls (line 66) | private function update_assets_urls( string $content ): string {
method localize_texts (line 80) | private function localize_texts( string $content ): string {
method load_demo_content_from_file (line 164) | private function load_demo_content_from_file(): string {
FILE: includes/Discovery.php
class Discovery (line 41) | class Discovery extends Service_Base implements HasRequirements {
method __construct (line 55) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 68) | public static function get_requirements(): array {
method register (line 77) | public function register(): void {
method print_document_title (line 115) | public function print_document_title(): void {
method print_metadata (line 143) | public function print_metadata(): void {
method print_schemaorg_metadata (line 165) | public function print_schemaorg_metadata(): void {
method print_open_graph_metadata (line 189) | public function print_open_graph_metadata(): void {
method print_twitter_metadata (line 214) | public function print_twitter_metadata(): void {
method print_feed_link (line 238) | public function print_feed_link(): void {
method get_schemaorg_metadata (line 288) | protected function get_schemaorg_metadata(): array {
method get_product_data (line 385) | protected function get_product_data( array $products ): array {
method get_open_graph_metadata (line 438) | protected function get_open_graph_metadata(): array {
method get_twitter_metadata (line 489) | protected function get_twitter_metadata(): array {
FILE: includes/Embed_Base.php
class Embed_Base (line 39) | abstract class Embed_Base extends Service_Base {
method __construct (line 67) | public function __construct( Assets $assets, Context $context ) {
method register (line 77) | public function register(): void {
method get_registration_action_priority (line 98) | public static function get_registration_action_priority(): int {
method add_amp_post_template_css (line 107) | public function add_amp_post_template_css(): void {
method filter_kses_allowed_html (line 128) | public function filter_kses_allowed_html( $allowed_tags ) {
method render_story (line 151) | public function render_story( Story $story, array $attributes ): string {
method render (line 171) | public function render( array $attributes ): string {
method default_attrs (line 199) | protected function default_attrs(): array {
FILE: includes/Exception/FailedToMakeInstance.php
class FailedToMakeInstance (line 42) | final class FailedToMakeInstance extends RuntimeException implements Web...
method for_circular_reference (line 65) | public static function for_circular_reference(
method for_unresolved_interface (line 90) | public static function for_unresolved_interface( string $interface_nam...
method for_unreflectable_class (line 108) | public static function for_unreflectable_class( string $interface_or_c...
method for_unresolved_argument (line 128) | public static function for_unresolved_argument( string $argument_name,...
method for_uninstantiated_shared_instance (line 146) | public static function for_uninstantiated_shared_instance( string $cla...
method for_invalid_delegate (line 163) | public static function for_invalid_delegate( string $class_name ): self {
FILE: includes/Exception/InvalidEventProperties.php
class InvalidEventProperties (line 40) | final class InvalidEventProperties extends InvalidArgumentException impl...
method from_invalid_type (line 50) | public static function from_invalid_type( $properties ): self {
method from_invalid_element_key_type (line 71) | public static function from_invalid_element_key_type( $property ): self {
method from_invalid_element_value_type (line 90) | public static function from_invalid_element_value_type( $property ): s...
FILE: includes/Exception/InvalidService.php
class InvalidService (line 40) | final class InvalidService extends InvalidArgumentException implements W...
method from_service (line 51) | public static function from_service( $service ): self {
method from_service_id (line 69) | public static function from_service_id( string $service_id ): self {
FILE: includes/Exception/SanitizationException.php
class SanitizationException (line 40) | final class SanitizationException extends RuntimeException implements We...
method from_document_parse_error (line 47) | public static function from_document_parse_error(): self {
FILE: includes/Exception/WebStoriesException.php
type WebStoriesException (line 42) | interface WebStoriesException {
FILE: includes/Experiments.php
class Experiments (line 46) | class Experiments extends Service_Base implements HasRequirements {
method __construct (line 67) | public function __construct( Settings $settings ) {
method register (line 74) | public function register(): void {
method get_requirements (line 90) | public static function get_requirements(): array {
method add_menu_page (line 99) | public function add_menu_page(): void {
method render (line 116) | public function render(): void {
method initialize_settings (line 125) | public function initialize_settings(): void {
method display_experiment_field (line 176) | public function display_experiment_field( array $args ): void {
method display_experiment_section (line 200) | public function display_experiment_section(): void {
method get_experiment_groups (line 217) | public function get_experiment_groups(): array {
method get_experiments (line 236) | public function get_experiments(): array {
method get_experiment_statuses (line 304) | public function get_experiment_statuses( string $group ): array {
method is_experiment_enabled (line 333) | public function is_experiment_enabled( string $name ): bool {
method get_enabled_experiments (line 361) | public function get_enabled_experiments(): array {
method get_experiment (line 378) | protected function get_experiment( string $name ): ?array {
FILE: includes/Font_Post_Type.php
class Font_Post_Type (line 39) | class Font_Post_Type extends Post_Type_Base implements HasRequirements {
method __construct (line 60) | public function __construct( Story_Post_Type $story_post_type ) {
method get_slug (line 69) | public function get_slug(): string {
method get_requirements (line 82) | public static function get_requirements(): array {
method get_args (line 95) | protected function get_args(): array {
FILE: includes/Infrastructure/Conditional.php
type Conditional (line 36) | interface Conditional {
method is_needed (line 45) | public static function is_needed(): bool;
FILE: includes/Infrastructure/Delayed.php
type Delayed (line 36) | interface Delayed {
method get_registration_action (line 45) | public static function get_registration_action(): string;
method get_registration_action_priority (line 55) | public static function get_registration_action_priority(): int;
FILE: includes/Infrastructure/HasMeta.php
type HasMeta (line 22) | interface HasMeta {
method register_meta (line 28) | public function register_meta(): void;
FILE: includes/Infrastructure/HasRequirements.php
type HasRequirements (line 36) | interface HasRequirements {
method get_requirements (line 45) | public static function get_requirements(): array;
FILE: includes/Infrastructure/Injector.php
type Injector (line 45) | interface Injector extends Service {
method make (line 65) | public function make( string $interface_or_class, array $arguments = [...
method bind (line 81) | public function bind( string $from, string $to ): Injector;
method bind_argument (line 95) | public function bind_argument(
method share (line 111) | public function share( string $interface_or_class ): Injector;
method delegate (line 125) | public function delegate( string $interface_or_class, callable $callba...
FILE: includes/Infrastructure/Injector/FallbackInstantiator.php
class FallbackInstantiator (line 31) | final class FallbackInstantiator implements Instantiator {
method instantiate (line 46) | public function instantiate( string $class_name, array $dependencies =...
FILE: includes/Infrastructure/Injector/InjectionChain.php
class InjectionChain (line 35) | final class InjectionChain {
method add_to_chain (line 63) | public function add_to_chain( string $class_name ): self {
method add_resolution (line 80) | public function add_resolution( string $resolution ): self {
method get_class (line 98) | public function get_class(): string {
method get_chain (line 117) | public function get_chain(): array {
method has_resolution (line 131) | public function has_resolution( string $resolution ): bool {
method is_in_chain (line 143) | public function is_in_chain( string $class_name ): bool {
FILE: includes/Infrastructure/Injector/SimpleInjector.php
class SimpleInjector (line 39) | final class SimpleInjector implements Injector {
method __construct (line 83) | public function __construct( ?Instantiator $instantiator = null ) {
method make (line 100) | public function make( string $interface_or_class, array $arguments = [...
method bind (line 149) | public function bind( string $from, string $to ): Injector {
method bind_argument (line 164) | public function bind_argument(
method share (line 184) | public function share( string $interface_or_class ): Injector {
method delegate (line 200) | public function delegate( string $interface_or_class, callable $callba...
method make_dependency (line 217) | private function make_dependency(
method resolve (line 267) | private function resolve(
method get_dependencies_for (line 301) | private function get_dependencies_for(
method ensure_is_instantiable (line 333) | private function ensure_is_instantiable( ReflectionClass $reflection )...
method resolve_argument (line 350) | private function resolve_argument(
method resolve_argument_by_name (line 401) | private function resolve_argument_by_name(
method has_shared_instance (line 447) | private function has_shared_instance( string $class_name ): bool {
method get_shared_instance (line 465) | private function get_shared_instance( string $class_name ) {
method has_delegate (line 489) | private function has_delegate( string $class_name ): bool {
method get_delegate (line 503) | private function get_delegate( string $class_name ): callable {
method get_class_reflection (line 521) | private function get_class_reflection( string $class_name ): Reflectio...
FILE: includes/Infrastructure/Instantiator.php
type Instantiator (line 34) | interface Instantiator {
method instantiate (line 46) | public function instantiate( string $class_name, array $dependencies =...
FILE: includes/Infrastructure/Plugin.php
type Plugin (line 40) | interface Plugin extends PluginActivationAware, PluginDeactivationAware,...
method get_container (line 50) | public function get_container(): ServiceContainer;
FILE: includes/Infrastructure/PluginActivationAware.php
type PluginActivationAware (line 35) | interface PluginActivationAware {
method on_plugin_activation (line 44) | public function on_plugin_activation( bool $network_wide ): void;
FILE: includes/Infrastructure/PluginDeactivationAware.php
type PluginDeactivationAware (line 35) | interface PluginDeactivationAware {
method on_plugin_deactivation (line 44) | public function on_plugin_deactivation( bool $network_wide ): void;
FILE: includes/Infrastructure/PluginUninstallAware.php
type PluginUninstallAware (line 39) | interface PluginUninstallAware {
method on_plugin_uninstall (line 46) | public function on_plugin_uninstall(): void;
FILE: includes/Infrastructure/Registerable.php
type Registerable (line 38) | interface Registerable {
method register (line 45) | public function register(): void;
FILE: includes/Infrastructure/Service.php
type Service (line 33) | interface Service {
FILE: includes/Infrastructure/ServiceBasedPlugin.php
class ServiceBasedPlugin (line 42) | abstract class ServiceBasedPlugin implements Plugin {
method __construct (line 94) | public function __construct(
method on_plugin_activation (line 123) | public function on_plugin_activation( bool $network_wide ): void {
method on_plugin_deactivation (line 152) | public function on_plugin_deactivation( bool $network_wide ): void {
method on_site_initialization (line 181) | public function on_site_initialization( WP_Site $site ): void {
method on_site_removal (line 217) | public function on_site_removal( WP_Site $site ): void {
method on_site_uninstall (line 247) | public function on_site_uninstall(): void {
method register (line 272) | public function register(): void {
method register_services (line 290) | public function register_services(): void {
method get_container (line 359) | public function get_container(): ServiceContainer {
method get_registration_action_priority (line 376) | protected function get_registration_action_priority( string $class_nam...
method requirements_are_met (line 432) | protected function requirements_are_met( string $id, string $class_nam...
method collect_missing_requirements (line 517) | protected function collect_missing_requirements( string $class_name, a...
method validate_services (line 559) | protected function validate_services( array $services ): array {
method get_identifier_from_fqcn (line 595) | protected function get_identifier_from_fqcn( string $fqcn ): string {
method schedule_potential_service_registration (line 620) | protected function schedule_potential_service_registration( string $id...
method maybe_register_service (line 651) | protected function maybe_register_service( string $id, string $class_n...
method instantiate_service (line 684) | protected function instantiate_service( $class_name ): Service {
method configure_injector (line 726) | protected function configure_injector( Injector $injector ): Injector {
method get_service_classes (line 846) | protected function get_service_classes(): array {
method get_bindings (line 860) | protected function get_bindings(): array {
method get_arguments (line 875) | protected function get_arguments(): array {
method get_shared_instances (line 892) | protected function get_shared_instances(): array {
method get_delegations (line 908) | protected function get_delegations(): array {
method maybe_resolve (line 925) | protected function maybe_resolve( $value ): string {
FILE: includes/Infrastructure/ServiceContainer.php
type ServiceContainer (line 40) | interface ServiceContainer extends Traversable, Countable, ArrayAccess {
method get (line 52) | public function get( string $id ): Service;
method has (line 62) | public function has( string $id ): bool;
method put (line 73) | public function put( string $id, Service $service ): void;
FILE: includes/Infrastructure/ServiceContainer/LazilyInstantiatedService.php
class LazilyInstantiatedService (line 33) | final class LazilyInstantiatedService implements Service {
method __construct (line 47) | public function __construct( callable $instantiation ) {
method instantiate (line 60) | public function instantiate(): Service {
FILE: includes/Infrastructure/ServiceContainer/SimpleServiceContainer.php
class SimpleServiceContainer (line 37) | final class SimpleServiceContainer extends ArrayObject implements Servic...
method get (line 49) | public function get( string $id ): Service {
method has (line 78) | public function has( string $id ): bool {
method put (line 91) | public function put( string $id, Service $service ): void {
FILE: includes/Infrastructure/SiteInitializationAware.php
type SiteInitializationAware (line 27) | interface SiteInitializationAware {
method on_site_initialization (line 36) | public function on_site_initialization( WP_Site $site ): void;
FILE: includes/Infrastructure/SiteRemovalAware.php
type SiteRemovalAware (line 27) | interface SiteRemovalAware {
method on_site_removal (line 36) | public function on_site_removal( WP_Site $site ): void;
FILE: includes/Integrations/AMP.php
class AMP (line 58) | class AMP extends Service_Base implements HasRequirements {
method __construct (line 95) | public function __construct(
method register (line 110) | public function register(): void {
method get_requirements (line 131) | public static function get_requirements(): array {
method filter_amp_options (line 149) | public function filter_amp_options( $options ) {
method filter_supportable_post_types (line 174) | public function filter_supportable_post_types( $post_types ) {
method add_amp_content_sanitizers (line 201) | public function add_amp_content_sanitizers( $sanitizers ) {
method filter_amp_validation_error_sanitized (line 270) | public function filter_amp_validation_error_sanitized( ?bool $sanitize...
method filter_amp_to_amp_linking_element_excluded (line 309) | public function filter_amp_to_amp_linking_element_excluded( $excluded,...
method filter_amp_skip_post (line 332) | public function filter_amp_skip_post( $skipped, int $post ) {
method get_request_post_type (line 354) | protected function get_request_post_type(): ?string {
method get_validated_url_post_type (line 419) | protected function get_validated_url_post_type( int $post_id ): ?string {
FILE: includes/Integrations/Conditional_Featured_Image.php
class Conditional_Featured_Image (line 37) | class Conditional_Featured_Image extends Service_Base {
method __construct (line 53) | public function __construct( Story_Post_Type $story_post_type ) {
method register (line 62) | public function register(): void {
method cybocfi_enabled_for_post_type (line 75) | public function cybocfi_enabled_for_post_type( $enabled, string $post_...
FILE: includes/Integrations/Core_Themes_Support.php
class Core_Themes_Support (line 39) | class Core_Themes_Support extends Service_Base {
method __construct (line 74) | public function __construct( Assets $assets ) {
method extend_theme_support (line 86) | public function extend_theme_support(): void {
method embed_web_stories (line 97) | public function embed_web_stories(): void {
method add_core_theme_classes (line 121) | public function add_core_theme_classes( $classes ) {
method register (line 135) | public function register(): void {
method get_registration_action (line 167) | public static function get_registration_action(): string {
FILE: includes/Integrations/Ezoic.php
class Ezoic (line 43) | class Ezoic extends Service_Base implements Conditional {
method __construct (line 74) | public function __construct( Sanitization $sanitization, Optimization ...
method register (line 85) | public function register(): void {
method is_needed (line 96) | public static function is_needed(): bool {
method process_ez_buffered_final_content (line 108) | public function process_ez_buffered_final_content( string $content ): ...
method render_error_page (line 137) | private function render_error_page( Throwable $throwable ): string {
FILE: includes/Integrations/Jetpack.php
class Jetpack (line 74) | class Jetpack extends Service_Base {
method __construct (line 112) | public function __construct( Media_Source_Taxonomy $media_source_taxon...
method register (line 122) | public function register(): void {
method add_to_jetpack_sitemap (line 151) | public function add_to_jetpack_sitemap( $post_types ) {
method add_videopress (line 174) | public function add_videopress( $mime_types ) {
method filter_ajax_query_attachments_args (line 204) | public function filter_ajax_query_attachments_args( $args ) {
method filter_admin_ajax_response (line 235) | public function filter_admin_ajax_response( $data, WP_Post $attachment...
method filter_rest_api_response (line 292) | public function filter_rest_api_response( WP_REST_Response $response, ...
method add_term (line 350) | public function add_term( int $mid, int $object_id, string $meta_key )...
method force_amp_request (line 369) | public function force_amp_request( bool $is_amp_request ): bool {
method format_milliseconds (line 383) | protected function format_milliseconds( int $milliseconds ): string {
FILE: includes/Integrations/New_Relic.php
class New_Relic (line 40) | class New_Relic extends Service_Base implements Conditional {
method __construct (line 53) | public function __construct( Context $context ) {
method register (line 62) | public function register(): void {
method get_registration_action (line 73) | public static function get_registration_action(): string {
method get_registration_action_priority (line 84) | public static function get_registration_action_priority(): int {
method is_needed (line 96) | public static function is_needed(): bool {
method disable_autorum (line 112) | public function disable_autorum(): void {
FILE: includes/Integrations/NextGen_Gallery.php
class NextGen_Gallery (line 37) | class NextGen_Gallery extends Service_Base {
method register (line 43) | public function register(): void {
method get_registration_action_priority (line 54) | public static function get_registration_action_priority(): int {
method filter_run_ngg_resource_manager (line 70) | public function filter_run_ngg_resource_manager( $valid_request ) {
method get_request_uri_path (line 100) | private function get_request_uri_path(): ?string {
FILE: includes/Integrations/Plugin_Status.php
class Plugin_Status (line 34) | class Plugin_Status {
method __construct (line 47) | public function __construct() {
method get_plugins (line 62) | public function get_plugins(): array {
FILE: includes/Integrations/ShortPixel.php
class ShortPixel (line 36) | class ShortPixel extends Service_Base {
method register (line 43) | public function register(): void {
method image_urls (line 55) | public function image_urls( array $urls ): array {
FILE: includes/Integrations/Site_Kit.php
class Site_Kit (line 46) | class Site_Kit extends Service_Base {
method __construct (line 83) | public function __construct( Analytics $analytics, Context $context, P...
method register (line 95) | public function register(): void {
method filter_site_kit_gtag_opt (line 133) | public function filter_site_kit_gtag_opt( $gtag_opt ) {
method get_plugin_status (line 161) | public function get_plugin_status(): array {
method is_plugin_active (line 228) | protected function is_plugin_active(): bool {
method is_adsense_module_active (line 240) | protected function is_adsense_module_active(): bool {
method is_analytics_module_active (line 257) | protected function is_analytics_module_active(): bool {
method get_site_kit_active_modules_option (line 278) | protected function get_site_kit_active_modules_option(): array {
FILE: includes/Integrations/WooCommerce.php
class WooCommerce (line 34) | class WooCommerce {
method __construct (line 52) | public function __construct( Plugin_Status $plugin_status ) {
method get_plugin_status (line 63) | public function get_plugin_status(): array {
method is_plugin_active (line 107) | protected function is_plugin_active(): bool {
FILE: includes/Interfaces/Field.php
type Field (line 18) | interface Field {
method show (line 25) | public function show(): bool;
method label (line 32) | public function label(): string;
method hidden (line 39) | public function hidden(): bool;
FILE: includes/Interfaces/FieldState.php
type FieldState (line 20) | interface FieldState {
method title (line 30) | public function title();
method excerpt (line 40) | public function excerpt();
method image_alignment (line 50) | public function image_alignment();
method author (line 60) | public function author();
method date (line 70) | public function date();
method archive_link (line 80) | public function archive_link();
method sharp_corners (line 90) | public function sharp_corners();
method circle_size (line 100) | public function circle_size();
method number_of_columns (line 110) | public function number_of_columns();
FILE: includes/Interfaces/FieldStateFactory.php
type FieldStateFactory (line 20) | interface FieldStateFactory {
method get_field (line 29) | public function get_field();
FILE: includes/Interfaces/Migration.php
type Migration (line 34) | interface Migration {
method migrate (line 41) | public function migrate(): void;
FILE: includes/Interfaces/Product_Query.php
type Product_Query (line 37) | interface Product_Query {
method get_search (line 50) | public function get_search( string $search_term, int $page = 1, int $p...
FILE: includes/Interfaces/Renderer.php
type Renderer (line 36) | interface Renderer {
method init (line 44) | public function init(): void;
method render (line 54) | public function render( array $args = [] ): string;
method render_single_story_content (line 63) | public function render_single_story_content();
FILE: includes/KSES.php
class KSES (line 52) | class KSES extends Service_Base implements HasRequirements {
method __construct (line 76) | public function __construct(
method register (line 89) | public function register(): void {
method get_requirements (line 102) | public static function get_requirements(): array {
method filter_insert_post_data (line 129) | public function filter_insert_post_data( $data, $postarr, $unsanitized...
method sanitize_content (line 168) | private function sanitize_content( string $content ): string {
method get_sanitizers (line 191) | private function get_sanitizers(): array {
method is_allowed_post_type (line 218) | private function is_allowed_post_type( string $post_type, $post_parent...
method filter_story_data (line 252) | private function filter_story_data( string $story_data ): string {
FILE: includes/Locale.php
class Locale (line 39) | class Locale {
method get_locale_settings (line 47) | public function get_locale_settings(): array {
FILE: includes/Media/Base_Color.php
class Base_Color (line 38) | class Base_Color extends Service_Base implements HasMeta, PluginUninstal...
method register (line 50) | public function register(): void {
method register_meta (line 61) | public function register_meta(): void {
method wp_prepare_attachment_for_js (line 92) | public function wp_prepare_attachment_for_js( $response ) {
method on_plugin_uninstall (line 114) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Blurhash.php
class Blurhash (line 38) | class Blurhash extends Service_Base implements HasMeta, PluginUninstallA...
method register (line 50) | public function register(): void {
method register_meta (line 61) | public function register_meta(): void {
method wp_prepare_attachment_for_js (line 91) | public function wp_prepare_attachment_for_js( $response ) {
method on_plugin_uninstall (line 113) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Cropping.php
class Cropping (line 38) | class Cropping extends Service_Base implements HasMeta, PluginUninstallA...
method register (line 50) | public function register(): void {
method register_meta (line 60) | public function register_meta(): void {
method delete_video (line 83) | public function delete_video( int $attachment_id ): void {
method on_plugin_uninstall (line 92) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Image_Sizes.php
class Image_Sizes (line 37) | class Image_Sizes extends Service_Base {
method register (line 73) | public function register(): void {
method wp_prepare_attachment_for_js (line 91) | public function wp_prepare_attachment_for_js( $response, WP_Post $atta...
method add_image_sizes (line 148) | protected function add_image_sizes(): void {
FILE: includes/Media/Media_Source_Taxonomy.php
class Media_Source_Taxonomy (line 44) | class Media_Source_Taxonomy extends Taxonomy_Base {
method __construct (line 69) | public function __construct( Context $context ) {
method register (line 80) | public function register(): void {
method on_site_initialization (line 101) | public function on_site_initialization( WP_Site $site ): void {
method on_plugin_activation (line 114) | public function on_plugin_activation( bool $network_wide ): void {
method get_all_terms (line 127) | public function get_all_terms(): array {
method rest_api_init (line 151) | public function rest_api_init(): void {
method wp_prepare_attachment_for_js (line 182) | public function wp_prepare_attachment_for_js( $response ) {
method get_callback_media_source (line 200) | public function get_callback_media_source( array $prepared ): string {
method update_callback_media_source (line 225) | public function update_callback_media_source( string $value, WP_Post $...
method filter_ajax_query_attachments_args (line 248) | public function filter_ajax_query_attachments_args( $args ) {
method filter_generated_media_attachments (line 268) | public function filter_generated_media_attachments( WP_Query $query ):...
method filter_rest_generated_media_attachments (line 290) | public function filter_rest_generated_media_attachments( $args ) {
method add_missing_terms (line 306) | private function add_missing_terms(): void {
method taxonomy_args (line 335) | protected function taxonomy_args(): array {
method get_exclude_tax_query (line 353) | private function get_exclude_tax_query( array $args ): array {
FILE: includes/Media/SVG.php
class SVG (line 43) | class SVG extends Service_Base {
method __construct (line 85) | public function __construct( Experiments $experiments ) {
method register (line 94) | public function register(): void {
method upload_mimes_add_svg (line 123) | public function upload_mimes_add_svg( array $mime_types ): array {
method mime_types_add_svg (line 140) | public function mime_types_add_svg( array $mime_types ): array {
method web_stories_allowed_mime_types (line 155) | public function web_stories_allowed_mime_types( array $mime_types ): a...
method filter_list_of_allowed_filetypes (line 169) | public function filter_list_of_allowed_filetypes( string $value ): str...
method wp_generate_attachment_metadata (line 190) | public function wp_generate_attachment_metadata( array $metadata, int ...
method wp_handle_upload (line 237) | public function wp_handle_upload( array $upload ): array {
method wp_check_filetype_and_ext (line 277) | public function wp_check_filetype_and_ext( array $wp_check_filetype_an...
method svg_already_enabled (line 294) | private function svg_already_enabled(): bool {
method get_svg_size (line 314) | protected function get_svg_size( string $file ) {
method sanitize (line 352) | protected function sanitize( string $file ) {
method get_xml (line 377) | protected function get_xml( string $svg ) {
method get_svg_data (line 408) | protected function get_svg_data( string $file ): string {
FILE: includes/Media/Types.php
class Types (line 34) | class Types {
method get_file_type_exts (line 43) | public function get_file_type_exts( array $mime_types = [] ): array {
method get_allowed_mime_types (line 64) | public function get_allowed_mime_types(): array {
FILE: includes/Media/Video/Captions.php
class Captions (line 36) | class Captions extends Service_Base {
method register (line 42) | public function register(): void {
method filter_list_of_allowed_filetypes (line 52) | public function filter_list_of_allowed_filetypes( $value ) {
FILE: includes/Media/Video/Is_Gif.php
class Is_Gif (line 38) | class Is_Gif extends Service_Base implements HasMeta, PluginUninstallAwa...
method register (line 49) | public function register(): void {
method register_meta (line 58) | public function register_meta(): void {
method wp_prepare_attachment_for_js (line 86) | public function wp_prepare_attachment_for_js( $response ) {
method on_plugin_uninstall (line 108) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Video/Muting.php
class Muting (line 40) | class Muting extends Service_Base implements HasMeta, PluginUninstallAwa...
method register (line 62) | public function register(): void {
method register_meta (line 75) | public function register_meta(): void {
method rest_api_init (line 108) | public function rest_api_init(): void {
method wp_prepare_attachment_for_js (line 140) | public function wp_prepare_attachment_for_js( $response ) {
method get_callback_is_muted (line 159) | public function get_callback_is_muted( array $prepared ): ?bool {
method update_callback_is_muted (line 190) | public function update_callback_is_muted( $value, WP_Post $post ) {
method delete_video (line 219) | public function delete_video( int $attachment_id ): void {
method on_plugin_uninstall (line 228) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Video/Optimization.php
class Optimization (line 38) | class Optimization extends Service_Base implements HasMeta, PluginUninst...
method register (line 50) | public function register(): void {
method register_meta (line 60) | public function register_meta(): void {
method delete_video (line 83) | public function delete_video( int $attachment_id ): void {
method on_plugin_uninstall (line 92) | public function on_plugin_uninstall(): void {
FILE: includes/Media/Video/Poster.php
class Poster (line 40) | class Poster extends Service_Base implements HasMeta, PluginUninstallAwa...
method __construct (line 65) | public function __construct( Media_Source_Taxonomy $media_source_taxon...
method register (line 74) | public function register(): void {
method register_meta (line 86) | public function register_meta(): void {
method rest_api_init (line 107) | public function rest_api_init(): void {
method get_callback_featured_media_src (line 157) | public function get_callback_featured_media_src( array $prepared ): ar...
method wp_prepare_attachment_for_js (line 185) | public function wp_prepare_attachment_for_js( $response, WP_Post $atta...
method get_thumbnail_data (line 211) | public function get_thumbnail_data( int $thumbnail_id ): array {
method delete_video_poster (line 233) | public function delete_video_poster( int $attachment_id ): void {
method on_plugin_uninstall (line 257) | public function on_plugin_uninstall(): void {
method is_poster (line 269) | protected function is_poster( int $post_id ): bool {
FILE: includes/Media/Video/Trimming.php
class Trimming (line 38) | class Trimming extends Service_Base implements HasMeta, PluginUninstallA...
method register (line 55) | public function register(): void {
method register_meta (line 66) | public function register_meta(): void {
method wp_prepare_attachment_for_js (line 112) | public function wp_prepare_attachment_for_js( $response ) {
method on_plugin_uninstall (line 135) | public function on_plugin_uninstall(): void {
FILE: includes/Mgid.php
class Mgid (line 36) | class Mgid extends Service_Base implements HasRequirements {
method __construct (line 52) | public function __construct( Settings $settings ) {
method register (line 61) | public function register(): void {
method get_requirements (line 74) | public static function get_requirements(): array {
method print_mgid_tag (line 83) | public function print_mgid_tag(): void {
method get_widget_id (line 124) | private function get_widget_id(): string {
method is_enabled (line 138) | private function is_enabled(): bool {
FILE: includes/Migrations/Add_Media_Source.php
class Add_Media_Source (line 36) | abstract class Add_Media_Source extends Migrate_Base {
method __construct (line 51) | public function __construct( Media_Source_Taxonomy $media_source_taxon...
method migrate (line 60) | public function migrate(): void {
method get_term (line 69) | abstract protected function get_term(): string;
FILE: includes/Migrations/Add_Media_Source_Editor.php
class Add_Media_Source_Editor (line 34) | class Add_Media_Source_Editor extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Gif_Conversion.php
class Add_Media_Source_Gif_Conversion (line 34) | class Add_Media_Source_Gif_Conversion extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Page_Template.php
class Add_Media_Source_Page_Template (line 34) | class Add_Media_Source_Page_Template extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Recording.php
class Add_Media_Source_Recording (line 34) | class Add_Media_Source_Recording extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Source_Image.php
class Add_Media_Source_Source_Image (line 34) | class Add_Media_Source_Source_Image extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Source_Video.php
class Add_Media_Source_Source_Video (line 34) | class Add_Media_Source_Source_Video extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Media_Source_Video_Optimization.php
class Add_Media_Source_Video_Optimization (line 34) | class Add_Media_Source_Video_Optimization extends Add_Media_Source {
method get_term (line 40) | protected function get_term(): string {
FILE: includes/Migrations/Add_Poster_Generation_Media_Source.php
class Add_Poster_Generation_Media_Source (line 36) | class Add_Poster_Generation_Media_Source extends Migration_Meta_To_Term {
method migrate (line 43) | public function migrate(): void {
method get_post_meta_key (line 53) | protected function get_post_meta_key(): string {
FILE: includes/Migrations/Add_Stories_Caps.php
class Add_Stories_Caps (line 36) | class Add_Stories_Caps extends Migrate_Base {
method __construct (line 51) | public function __construct( Capabilities $capabilities ) {
method migrate (line 60) | public function migrate(): void {
FILE: includes/Migrations/Add_VideoPress_Poster_Generation_Media_Source.php
class Add_VideoPress_Poster_Generation_Media_Source (line 36) | class Add_VideoPress_Poster_Generation_Media_Source extends Migration_Me...
method get_post_meta_key (line 42) | protected function get_post_meta_key(): string {
FILE: includes/Migrations/Migrate_Base.php
class Migrate_Base (line 38) | abstract class Migrate_Base implements Migration {
FILE: includes/Migrations/Migration_Meta_To_Term.php
class Migration_Meta_To_Term (line 36) | abstract class Migration_Meta_To_Term extends Migrate_Base {
method __construct (line 52) | public function __construct( Media_Source_Taxonomy $media_source_taxon...
method migrate (line 63) | public function migrate(): void {
method get_post_meta_key (line 91) | abstract protected function get_post_meta_key(): string;
method get_term_name (line 99) | protected function get_term_name(): string {
FILE: includes/Migrations/Remove_Broken_Text_Styles.php
class Remove_Broken_Text_Styles (line 51) | class Remove_Broken_Text_Styles extends Migrate_Base {
method migrate (line 57) | public function migrate(): void {
FILE: includes/Migrations/Remove_Incorrect_Tracking_Id.php
class Remove_Incorrect_Tracking_Id (line 37) | class Remove_Incorrect_Tracking_Id extends Migrate_Base {
method __construct (line 53) | public function __construct( Settings $settings ) {
method migrate (line 62) | public function migrate(): void {
FILE: includes/Migrations/Remove_Unneeded_Attachment_Meta.php
class Remove_Unneeded_Attachment_Meta (line 36) | class Remove_Unneeded_Attachment_Meta extends Migrate_Base {
method migrate (line 44) | public function migrate(): void {
FILE: includes/Migrations/Replace_Conic_Style_Presets.php
class Replace_Conic_Style_Presets (line 47) | class Replace_Conic_Style_Presets extends Migrate_Base {
method migrate (line 53) | public function migrate(): void {
FILE: includes/Migrations/Rewrite_Flush.php
class Rewrite_Flush (line 36) | class Rewrite_Flush extends Migrate_Base {
method migrate (line 43) | public function migrate(): void {
FILE: includes/Migrations/Set_Legacy_Analytics_Usage_Flag.php
class Set_Legacy_Analytics_Usage_Flag (line 36) | class Set_Legacy_Analytics_Usage_Flag extends Migrate_Base {
method __construct (line 52) | public function __construct( Settings $settings ) {
method migrate (line 61) | public function migrate(): void {
FILE: includes/Migrations/Unify_Color_Presets.php
class Unify_Color_Presets (line 36) | class Unify_Color_Presets extends Migrate_Base {
method migrate (line 45) | public function migrate(): void {
FILE: includes/Migrations/Update_1.php
class Update_1 (line 34) | class Update_1 extends Migrate_Base {
method migrate (line 40) | public function migrate(): void {
FILE: includes/Migrations/Update_Publisher_Logos.php
class Update_Publisher_Logos (line 36) | class Update_Publisher_Logos extends Migrate_Base {
method __construct (line 52) | public function __construct( Settings $settings ) {
method migrate (line 61) | public function migrate(): void {
FILE: includes/Model/Story.php
class Story (line 42) | class Story {
method __construct (line 133) | public function __construct( array $story = [] ) {
method load_from_post (line 148) | public function load_from_post( $_post ): bool {
method set_poster_sizes (line 243) | public function set_poster_sizes( string $poster_sizes ): void {
method set_poster_srcset (line 254) | public function set_poster_srcset( string $poster_srcset ): void {
method set_title (line 265) | public function set_title( string $title ): void {
method get_poster_sizes (line 274) | public function get_poster_sizes(): string {
method get_poster_srcset (line 283) | public function get_poster_srcset(): string {
method get_title (line 292) | public function get_title(): string {
method get_excerpt (line 299) | public function get_excerpt(): string {
method get_url (line 308) | public function get_url(): string {
method get_markup (line 317) | public function get_markup(): string {
method get_poster_portrait (line 326) | public function get_poster_portrait(): string {
method get_id (line 333) | public function get_id(): int {
method get_author (line 340) | public function get_author(): string {
method get_date (line 347) | public function get_date(): string {
method get_publisher_name (line 358) | public function get_publisher_name(): string {
method get_publisher_logo_url (line 369) | public function get_publisher_logo_url(): ?string {
method get_publisher_logo_size (line 399) | public function get_publisher_logo_size(): array {
method get_poster_portrait_size (line 434) | public function get_poster_portrait_size(): array {
method get_products (line 445) | public function get_products(): array {
FILE: includes/Page_Template_Post_Type.php
class Page_Template_Post_Type (line 39) | class Page_Template_Post_Type extends Post_Type_Base implements HasRequi...
method __construct (line 61) | public function __construct( Story_Post_Type $story_post_type ) {
method register (line 68) | public function register(): void {
method get_slug (line 79) | public function get_slug(): string {
method get_requirements (line 92) | public static function get_requirements(): array {
method delete_poster_image (line 106) | public function delete_poster_image( int $post_id ): void {
method get_args (line 127) | protected function get_args(): array {
FILE: includes/Plugin.php
class Plugin (line 41) | class Plugin extends ServiceBasedPlugin {
method get_service_classes (line 155) | protected function get_service_classes(): array {
method get_shared_instances (line 173) | protected function get_shared_instances(): array {
method get_delegations (line 210) | protected function get_delegations(): array {
FILE: includes/PluginFactory.php
class PluginFactory (line 47) | class PluginFactory extends ServiceBasedPlugin {
method create (line 57) | public static function create(): Plugin {
FILE: includes/Post_Type_Base.php
class Post_Type_Base (line 91) | abstract class Post_Type_Base extends Service_Base implements PluginActi...
method register (line 103) | public function register(): void {
method register_post_type (line 114) | public function register_post_type() {
method unregister_post_type (line 123) | public function unregister_post_type(): void {
method on_site_initialization (line 134) | public function on_site_initialization( WP_Site $site ): void {
method on_plugin_activation (line 145) | public function on_plugin_activation( bool $network_wide ): void {
method on_plugin_deactivation (line 156) | public function on_plugin_deactivation( bool $network_wide ): void {
method get_slug (line 167) | abstract public function get_slug(): string;
method get_rest_base (line 176) | public function get_rest_base(): string {
method get_rest_namespace (line 195) | public function get_rest_namespace(): string {
method get_rest_url (line 211) | public function get_rest_url(): string {
method get_caps (line 222) | public function get_caps(): array {
method has_cap (line 240) | public function has_cap( string $cap ): bool {
method get_cap_name (line 258) | public function get_cap_name( string $cap ) {
method get_label (line 280) | public function get_label( string $label ): string {
method get_parent_controller (line 302) | public function get_parent_controller(): WP_REST_Controller {
method get_archive_link (line 332) | public function get_archive_link( bool $ignore_has_archive = false ) {
method on_plugin_uninstall (line 361) | public function on_plugin_uninstall(): void {
method get_args (line 387) | abstract protected function get_args(): array;
method get_object (line 394) | protected function get_object(): ?WP_Post_Type {
FILE: includes/REST_API/Embed_Controller.php
class Embed_Controller (line 63) | class Embed_Controller extends REST_Controller implements HasRequirements {
method __construct (line 77) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 93) | public static function get_requirements(): array {
method register_routes (line 102) | public function register_routes(): void {
method get_proxy_item (line 136) | public function get_proxy_item( $request ) {
method prepare_item_for_response (line 257) | public function prepare_item_for_response( $embed, $request ) {
method get_item_schema (line 289) | public function get_item_schema(): array {
method get_proxy_item_permissions_check (line 337) | public function get_proxy_item_permissions_check() {
method get_data_from_post (line 353) | private function get_data_from_post( string $url ) {
method url_to_post (line 378) | private function url_to_post( $url ): ?WP_Post {
method maybe_switch_site (line 457) | private function maybe_switch_site( $url ): bool {
method get_data_from_document (line 524) | private function get_data_from_document( string $html ) {
method get_dom_attribute_content (line 564) | protected function get_dom_attribute_content( $query, string $attribut...
FILE: includes/REST_API/Font_Controller.php
class Font_Controller (line 74) | class Font_Controller extends WP_REST_Posts_Controller {
method register_routes (line 82) | public function register_routes(): void {
method get_items (line 133) | public function get_items( $request ) {
method get_items_permissions_check (line 215) | public function get_items_permissions_check( $request ) {
method delete_item (line 240) | public function delete_item( $request ) {
method prepare_item_for_response (line 259) | public function prepare_item_for_response( $item, $request ): WP_REST_...
method get_collection_params (line 334) | public function get_collection_params(): array {
method get_item_schema (line 382) | public function get_item_schema(): array {
method get_builtin_fonts (line 500) | protected function get_builtin_fonts(): array {
method get_custom_fonts (line 538) | protected function get_custom_fonts( $request ): array {
method prepare_item_for_database (line 624) | protected function prepare_item_for_database( $request ) {
method font_exists (line 682) | private function font_exists( string $font_family ): bool {
FILE: includes/REST_API/Hotlinking_Controller.php
class Hotlinking_Controller (line 92) | class Hotlinking_Controller extends REST_Controller implements HasRequir...
method __construct (line 129) | public function __construct( Story_Post_Type $story_post_type, Types $...
method get_requirements (line 146) | public static function get_requirements(): array {
method register_routes (line 157) | public function register_routes(): void {
method parse_url (line 214) | public function parse_url( WP_REST_Request $request ) {
method proxy_url (line 337) | public function proxy_url( WP_REST_Request $request ) {
method prepare_item_for_response (line 420) | public function prepare_item_for_response( $link, $request ) {
method get_item_schema (line 460) | public function get_item_schema(): array {
method parse_url_permissions_check (line 530) | public function parse_url_permissions_check() {
method validate_callback (line 550) | public function validate_callback( $value ) {
method get_curl_resolve_callback (line 574) | public function get_curl_resolve_callback( string $url, string $url_or...
method modify_curl_configuration (line 616) | public function modify_curl_configuration( $handle ): void {
method stream_headers (line 648) | public function stream_headers( $handle, $header ): int {
method proxy_url_curl (line 676) | private function proxy_url_curl( string $url, array $args ): void {
method proxy_url_fallback (line 699) | private function proxy_url_fallback( string $url, array $args ): void {
method validate_url (line 735) | private function validate_url( string $url ) { // phpcs:ignore Slevoma...
method get_allowed_mime_types (line 835) | protected function get_allowed_mime_types(): array {
FILE: includes/REST_API/Link_Controller.php
class Link_Controller (line 58) | class Link_Controller extends REST_Controller implements HasRequirements {
method __construct (line 72) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 88) | public static function get_requirements(): array {
method register_routes (line 99) | public function register_routes(): void {
method parse_link (line 134) | public function parse_link( $request ) {
method prepare_item_for_response (line 364) | public function prepare_item_for_response( $link, $request ) {
method get_item_schema (line 394) | public function get_item_schema(): array {
method parse_link_permissions_check (line 447) | public function parse_link_permissions_check() {
method validate_url (line 463) | public function validate_url( $value ) {
method get_dom_attribute_content (line 482) | protected function get_dom_attribute_content( $query, string $attribut...
FILE: includes/REST_API/Page_Template_Controller.php
class Page_Template_Controller (line 51) | class Page_Template_Controller extends Stories_Base_Controller {
method get_items (line 60) | public function get_items( $request ) {
method get_collection_params (line 87) | public function get_collection_params(): array {
method get_item_schema (line 111) | public function get_item_schema(): array {
method get_items_permissions_check (line 153) | public function get_items_permissions_check( $request ) {
method get_item_permissions_check (line 184) | public function get_item_permissions_check( $request ) {
FILE: includes/REST_API/Products_Controller.php
class Products_Controller (line 67) | class Products_Controller extends REST_Controller implements HasRequirem...
method __construct (line 98) | public function __construct( Settings $settings, Story_Post_Type $stor...
method get_requirements (line 116) | public static function get_requirements(): array {
method register_routes (line 127) | public function register_routes(): void {
method get_items_permissions_check (line 151) | public function get_items_permissions_check( $request ) {
method get_items (line 175) | public function get_items( $request ) {
method prepare_item_for_response (line 241) | public function prepare_item_for_response( $item, $request ): WP_REST_...
method get_item_schema (line 335) | public function get_item_schema(): array {
method get_collection_params (line 463) | public function get_collection_params(): array {
FILE: includes/REST_API/Publisher_Logos_Controller.php
class Publisher_Logos_Controller (line 47) | class Publisher_Logos_Controller extends REST_Controller implements HasR...
method __construct (line 69) | public function __construct( Settings $settings, Story_Post_Type $stor...
method get_requirements (line 86) | public static function get_requirements(): array {
method register_routes (line 97) | public function register_routes(): void {
method permissions_check (line 149) | public function permissions_check() {
method update_item_permissions_check (line 169) | public function update_item_permissions_check( $request ) {
method get_items (line 189) | public function get_items( $request ) {
method create_item (line 229) | public function create_item( $request ) {
method delete_item (line 317) | public function delete_item( $request ) {
method update_item (line 369) | public function update_item( $request ) {
method prepare_item_for_response (line 399) | public function prepare_item_for_response( $post, $request ): WP_REST_...
method get_item_schema (line 443) | public function get_item_schema(): array {
method get_publisher_logo (line 490) | protected function get_publisher_logo( $id ) {
method filter_publisher_logos (line 518) | protected function filter_publisher_logos( $publisher_logos ): array {
method prepare_links (line 532) | protected function prepare_links( $post ): array {
FILE: includes/REST_API/REST_Controller.php
class REST_Controller (line 39) | abstract class REST_Controller extends WP_REST_Controller implements Ser...
method register (line 45) | public function register(): void {
method get_registration_action (line 56) | public static function get_registration_action(): string {
method get_registration_action_priority (line 67) | public static function get_registration_action_priority(): int {
FILE: includes/REST_API/Status_Check_Controller.php
class Status_Check_Controller (line 55) | class Status_Check_Controller extends REST_Controller implements HasRequ...
method __construct (line 69) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 85) | public static function get_requirements(): array {
method register_routes (line 94) | public function register_routes(): void {
method status_check (line 123) | public function status_check( $request ) {
method prepare_item_for_response (line 144) | public function prepare_item_for_response( $item, $request ) {
method get_item_schema (line 170) | public function get_item_schema(): array {
method status_check_permissions_check (line 212) | public function status_check_permissions_check() {
FILE: includes/REST_API/Stories_Autosaves_Controller.php
class Stories_Autosaves_Controller (line 43) | class Stories_Autosaves_Controller extends WP_REST_Autosaves_Controller {
method __construct (line 62) | public function __construct( string $parent_post_type ) {
method register_routes (line 93) | public function register_routes(): void {
method prepare_item_for_response (line 136) | public function prepare_item_for_response( $post, $request ): WP_REST_...
method get_item_schema (line 178) | public function get_item_schema(): array {
FILE: includes/REST_API/Stories_Base_Controller.php
class Stories_Base_Controller (line 75) | class Stories_Base_Controller extends WP_REST_Posts_Controller {
method __construct (line 92) | public function __construct( $post_type ) {
method prepare_item_for_response (line 119) | public function prepare_item_for_response( $post, $request ): WP_REST_...
method get_item_schema (line 167) | public function get_item_schema(): array {
method prepare_item_for_database (line 212) | protected function prepare_item_for_database( $request ) {
method get_registered_meta (line 270) | protected function get_registered_meta( WP_Post $original_post ): array {
method prepare_links (line 300) | protected function prepare_links( $post ): array {
method get_available_actions (line 342) | protected function get_available_actions( $post, $request ): array {
FILE: includes/REST_API/Stories_Controller.php
class Stories_Controller (line 53) | class Stories_Controller extends Stories_Base_Controller {
method prepare_item_for_response (line 85) | public function prepare_item_for_response( $post, $request ): WP_REST_...
method create_item (line 186) | public function create_item( $request ) {
method update_item (line 242) | public function update_item( $request ) {
method get_item_schema (line 265) | public function get_item_schema(): array {
method filter_posts_clauses (line 347) | public function filter_posts_clauses( $clauses, WP_Query $query ): arr...
method prime_post_caches (line 380) | public function prime_post_caches( array $posts ): array {
method filter_query (line 397) | public function filter_query( $args ): array {
method get_items (line 412) | public function get_items( $request ) {
method get_collection_params (line 450) | public function get_collection_params(): array {
method get_attached_post_ids (line 480) | protected function get_attached_post_ids( array $posts ): array {
method add_response_headers (line 495) | protected function add_response_headers( WP_REST_Response $response, W...
method prepare_links (line 580) | protected function prepare_links( $post ): array {
method add_post_locking_link (line 601) | private function add_post_locking_link( array $links, WP_Post $post ):...
method get_publisher_logo_id (line 642) | private function get_publisher_logo_id( WP_Post $post ): int {
method add_publisher_logo_link (line 665) | private function add_publisher_logo_link( array $links, WP_Post $post ...
method get_story_poster (line 689) | private function get_story_poster( WP_Post $post ): ?array {
FILE: includes/REST_API/Stories_Lock_Controller.php
class Stories_Lock_Controller (line 42) | class Stories_Lock_Controller extends REST_Controller implements HasRequ...
method __construct (line 65) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 82) | public static function get_requirements(): array {
method register_routes (line 93) | public function register_routes(): void {
method get_item (line 137) | public function get_item( $request ) {
method update_item (line 158) | public function update_item( $request ) {
method delete_item (line 184) | public function delete_item( $request ): WP_REST_Response {
method get_item_permissions_check (line 216) | public function get_item_permissions_check( $request ) {
method update_item_permissions_check (line 226) | public function update_item_permissions_check( $request ) {
method delete_item_permissions_check (line 236) | public function delete_item_permissions_check( $request ) {
method prepare_item_for_response (line 275) | public function prepare_item_for_response( $item, $request ) { // phpc...
method get_item_schema (line 369) | public function get_item_schema(): array {
method get_lock (line 450) | protected function get_lock( int $post_id ) {
method prepare_links (line 478) | protected function prepare_links( $lock, int $post_id ): array {
FILE: includes/REST_API/Stories_Media_Controller.php
class Stories_Media_Controller (line 53) | class Stories_Media_Controller extends WP_REST_Attachments_Controller im...
method __construct (line 70) | public function __construct( Types $types ) {
method register (line 81) | public function register(): void {
method get_registration_action (line 92) | public static function get_registration_action(): string {
method get_registration_action_priority (line 103) | public static function get_registration_action_priority(): int {
method get_items (line 119) | public function get_items( $request ) {
method create_item (line 142) | public function create_item( $request ) {
method get_collection_params (line 191) | public function get_collection_params(): array {
method prepare_item_for_response (line 212) | public function prepare_item_for_response( $post, $request ): WP_REST_...
method get_item_schema (line 266) | public function get_item_schema(): array {
method process_post (line 301) | protected function process_post( $post_id, $parent_post, $original_id ) {
method prepare_items_query (line 356) | protected function prepare_items_query( $prepared_args = [], $request ...
method get_media_types (line 390) | protected function get_media_types(): array {
FILE: includes/REST_API/Stories_Settings_Controller.php
class Stories_Settings_Controller (line 39) | class Stories_Settings_Controller extends WP_REST_Settings_Controller im...
method __construct (line 47) | public function __construct() {
method register (line 57) | public function register(): void {
method get_registration_action (line 68) | public static function get_registration_action(): string {
method get_registration_action_priority (line 79) | public static function get_registration_action_priority(): int {
FILE: includes/REST_API/Stories_Taxonomies_Controller.php
class Stories_Taxonomies_Controller (line 45) | class Stories_Taxonomies_Controller extends WP_REST_Taxonomies_Controlle...
method __construct (line 53) | public function __construct() {
method get_items (line 70) | public function get_items( $request ) {
method get_collection_params (line 125) | public function get_collection_params(): array {
method register (line 148) | public function register(): void {
method get_registration_action (line 159) | public static function get_registration_action(): string {
method get_registration_action_priority (line 170) | public static function get_registration_action_priority(): int {
FILE: includes/REST_API/Stories_Terms_Controller.php
class Stories_Terms_Controller (line 37) | class Stories_Terms_Controller extends WP_REST_Terms_Controller {
method prepare_links (line 46) | protected function prepare_links( $term ): array {
FILE: includes/REST_API/Stories_Users_Controller.php
class Stories_Users_Controller (line 43) | class Stories_Users_Controller extends WP_REST_Users_Controller implemen...
method __construct (line 60) | public function __construct( Story_Post_Type $story_post_type ) {
method register (line 72) | public function register(): void {
method get_registration_action (line 83) | public static function get_registration_action(): string {
method get_registration_action_priority (line 94) | public static function get_registration_action_priority(): int {
method get_items_permissions_check (line 109) | public function get_items_permissions_check( $request ) {
method get_items (line 143) | public function get_items( $request ) {
method filter_query_args (line 177) | public function filter_query_args( array $prepared_args ): array {
method get_item_permissions_check (line 195) | public function get_item_permissions_check( $request ) {
method user_posts_count_public (line 246) | protected function user_posts_count_public( int $userid, string $post_...
FILE: includes/Register_Widget.php
class Register_Widget (line 36) | class Register_Widget extends Service_Base {
method __construct (line 51) | public function __construct( Stories $stories ) {
method register (line 60) | public function register(): void {
method register_widgets (line 71) | public function register_widgets(): void {
method hide_widget (line 87) | public function hide_widget( $widget_types ) {
method body_class (line 108) | public function body_class( $classes ) {
method get_registration_action_priority (line 126) | public static function get_registration_action_priority(): int {
FILE: includes/Remove_Transients.php
class Remove_Transients (line 37) | class Remove_Transients implements Service, PluginUninstallAware {
method on_plugin_uninstall (line 45) | public function on_plugin_uninstall(): void {
method delete_transients (line 80) | protected function delete_transients(): void {
method delete_network_transients (line 102) | protected function delete_network_transients(): void {
FILE: includes/Renderer/Archives.php
class Archives (line 43) | class Archives extends Service_Base {
method __construct (line 75) | public function __construct( Assets $assets, AMP_Story_Player_Assets $...
method register (line 86) | public function register(): void {
method embed_player (line 99) | public function embed_player( $content ) {
FILE: includes/Renderer/Feed.php
class Feed (line 40) | class Feed extends Service_Base {
method register (line 47) | public function register(): void {
method embed_image (line 60) | public function embed_image( $content ) {
FILE: includes/Renderer/Oembed.php
class Oembed (line 38) | class Oembed extends Service_Base {
method register (line 45) | public function register(): void {
method filter_embed_template (line 60) | public function filter_embed_template( $template ) {
method filter_embed_html (line 83) | public function filter_embed_html( $output, WP_Post $post, int $width,...
method filter_oembed_response_data (line 127) | public function filter_oembed_response_data( $data, WP_Post $post, int...
method get_embed_height_width (line 151) | protected function get_embed_height_width( int $old_width ): array {
FILE: includes/Renderer/Single.php
class Single (line 37) | class Single extends Service_Base {
method __construct (line 50) | public function __construct( Context $context ) {
method register (line 59) | public function register(): void {
method filter_template_include (line 77) | public function filter_template_include( $template ) {
method show_admin_bar (line 93) | public function show_admin_bar( $show ) {
FILE: includes/Renderer/Stories/Carousel_Renderer.php
class Carousel_Renderer (line 38) | class Carousel_Renderer extends Renderer {
method init (line 52) | public function init(): void {
method load_assets (line 66) | public function load_assets(): void {
method render (line 88) | public function render( array $args = [] ): string {
method get_carousel_settings (line 176) | protected function get_carousel_settings(): array {
FILE: includes/Renderer/Stories/FieldState/BaseFieldState.php
class BaseFieldState (line 34) | class BaseFieldState implements FieldState {
method __construct (line 46) | public function __construct( Story_Post_Type $story_post_type ) {
method image_alignment (line 57) | public function image_alignment() {
method excerpt (line 74) | public function excerpt() {
method author (line 91) | public function author() {
method date (line 108) | public function date() {
method archive_link (line 125) | public function archive_link() {
method title (line 142) | public function title() {
method sharp_corners (line 159) | public function sharp_corners() {
method circle_size (line 176) | public function circle_size() {
method number_of_columns (line 192) | public function number_of_columns() {
method prepare_field (line 209) | protected function prepare_field( array $args ): BaseField {
FILE: includes/Renderer/Stories/FieldState/CarouselView.php
class CarouselView (line 31) | final class CarouselView extends BaseFieldState {
method author (line 40) | public function author() {
FILE: includes/Renderer/Stories/FieldState/CircleView.php
class CircleView (line 31) | final class CircleView extends BaseFieldState {
method title (line 40) | public function title() {
method author (line 57) | public function author() {
method date (line 74) | public function date() {
method sharp_corners (line 91) | public function sharp_corners() {
method circle_size (line 108) | public function circle_size() {
FILE: includes/Renderer/Stories/FieldState/GridView.php
class GridView (line 31) | final class GridView extends BaseFieldState {
method number_of_columns (line 39) | public function number_of_columns() {
FILE: includes/Renderer/Stories/FieldState/ListView.php
class ListView (line 31) | final class ListView extends BaseFieldState {
method excerpt (line 40) | public function excerpt() {
method date (line 59) | public function date() {
method image_alignment (line 78) | public function image_alignment() {
FILE: includes/Renderer/Stories/FieldStateFactory/Factory.php
class Factory (line 42) | class Factory implements FieldStateFactory {
method __construct (line 56) | public function __construct( Injector $injector ) {
method get_field (line 68) | public function get_field( $view = 'grid' ) {
FILE: includes/Renderer/Stories/Fields/BaseField.php
class BaseField (line 31) | class BaseField implements Field {
method __construct (line 52) | public function __construct( array $args ) {
method label (line 63) | public function label(): string {
method show (line 72) | public function show(): bool {
method hidden (line 81) | public function hidden(): bool {
FILE: includes/Renderer/Stories/Generic_Renderer.php
class Generic_Renderer (line 44) | class Generic_Renderer extends Renderer {
method init (line 53) | public function init(): void {
method render (line 70) | public function render( array $args = [] ): string {
FILE: includes/Renderer/Stories/Renderer.php
class Renderer (line 52) | abstract class Renderer implements RenderingInterface, Iterator {
method __construct (line 143) | public function __construct( Story_Query $query ) {
method render (line 177) | public function render( array $args = [] ): string {
method current (line 197) | public function current(): ?Story {
method next (line 208) | public function next(): void {
method key (line 219) | #[\ReturnTypeWillChange]
method valid (line 231) | public function valid(): bool {
method rewind (line 242) | public function rewind(): void {
method init (line 253) | public function init(): void {
method load_assets (line 267) | public function load_assets(): void {
method add_amp_post_template_css (line 287) | public function add_amp_post_template_css(): void {
method prepare_stories (line 306) | public function prepare_stories( $post ): ?Story {
method render_single_story_content (line 342) | public function render_single_story_content(): void {
method render_stories_with_lightbox (line 405) | public function render_stories_with_lightbox(): void {
method render_stories_with_lightbox_amp (line 446) | public function render_stories_with_lightbox_amp(): void {
method render_stories_lightbox (line 456) | public function render_stories_lightbox(): void {
method is_view_type (line 482) | protected function is_view_type( $view_type ): bool {
method get_view_type (line 493) | protected function get_view_type(): string {
method maybe_render_archive_link (line 504) | protected function maybe_render_archive_link(): void {
method get_view_classes (line 535) | protected function get_view_classes(): string {
method get_container_classes (line 567) | protected function get_container_classes(): string {
method get_single_story_classes (line 591) | protected function get_single_story_classes(): string {
method get_container_styles (line 622) | protected function get_container_styles(): string {
method render_story_with_poster (line 645) | protected function render_story_with_poster(): void {
method render_link_attributes (line 708) | protected function render_link_attributes(): void {
method get_content_overlay (line 749) | protected function get_content_overlay(): void {
method generate_lightbox_html (line 804) | protected function generate_lightbox_html( $story ): void {
method generate_amp_lightbox_html_amp (line 824) | protected function generate_amp_lightbox_html_amp( $story ): void {
FILE: includes/Renderer/Story/Embed.php
class Embed (line 40) | class Embed {
method __construct (line 71) | public function __construct( Story $story, Assets $assets, Context $co...
method render (line 87) | public function render( array $args = [] ): string {
FILE: includes/Renderer/Story/HTML.php
class HTML (line 36) | class HTML {
method __construct (line 51) | public function __construct( Story $story ) {
method render (line 62) | public function render(): string {
method fix_incorrect_charset (line 85) | public function fix_incorrect_charset( string $content ): string {
method fix_malformed_script_link_tags (line 115) | protected function fix_malformed_script_link_tags( string $content ): ...
method get_html_head_markup (line 157) | protected function get_html_head_markup(): string {
method replace_html_head (line 180) | protected function replace_html_head( string $content ): string {
method print_analytics (line 206) | protected function print_analytics( string $content ): string {
method print_social_share (line 230) | protected function print_social_share( string $content ): string {
FILE: includes/Renderer/Story/Image.php
class Image (line 36) | class Image {
method __construct (line 52) | public function __construct( Story $story ) {
method render (line 64) | public function render( array $args = [] ): string {
FILE: includes/Renderer/Story/Singleton.php
class Singleton (line 40) | class Singleton {
method __construct (line 78) | public function __construct( Story $story, Assets $assets ) {
method render (line 93) | public function render( array $args = [] ): string {
method render_story_with_poster (line 197) | protected function render_story_with_poster( array $args ): void {
method render_content_overlay (line 242) | protected function render_content_overlay(): void {
FILE: includes/Service_Base.php
class Service_Base (line 40) | abstract class Service_Base implements Service, Delayed, Registerable {
method get_registration_action (line 48) | public static function get_registration_action(): string {
method get_registration_action_priority (line 59) | public static function get_registration_action_priority(): int {
FILE: includes/Services.php
class Services (line 20) | final class Services {
method get (line 46) | public static function get( string $service ): Service {
method has (line 57) | public static function has( string $service ): bool {
method get_plugin (line 68) | public static function get_plugin(): Plugin {
method get_container (line 83) | public static function get_container(): ServiceContainer {
method get_injector (line 98) | public static function get_injector(): Injector {
FILE: includes/Settings.php
class Settings (line 39) | class Settings extends Service_Base implements PluginUninstallAware {
method __construct (line 167) | public function __construct( Shopping_Vendors $shopping_vendors ) {
method prime_option_caches (line 176) | public function prime_option_caches(): void {
method register (line 188) | public function register(): void {
method get_setting (line 463) | public function get_setting( string $key, $default_value = false ) {
method update_setting (line 512) | public function update_setting( string $key, $value ) {
method on_plugin_uninstall (line 521) | public function on_plugin_uninstall(): void {
method get_registered_options (line 555) | protected function get_registered_options(): array {
FILE: includes/Shopping/Product.php
class Product (line 56) | class Product implements JsonSerializable {
method __construct (line 110) | public function __construct( array $product = [] ) {
method get_id (line 123) | public function get_id(): string {
method get_title (line 132) | public function get_title(): string {
method get_brand (line 141) | public function get_brand(): string {
method get_price (line 150) | public function get_price(): float {
method get_price_currency (line 159) | public function get_price_currency(): string {
method get_images (line 170) | public function get_images(): array {
method get_details (line 179) | public function get_details(): string {
method get_url (line 188) | public function get_url(): string {
method get_aggregate_rating (line 199) | public function get_aggregate_rating(): ?array {
method jsonSerialize (line 210) | #[\ReturnTypeWillChange]
method load_from_array (line 246) | public static function load_from_array( array $product ): Product {
method set_id (line 278) | protected function set_id( string $id ): void {
method set_title (line 289) | protected function set_title( string $title ): void {
method set_brand (line 300) | protected function set_brand( string $brand ): void {
method set_price (line 311) | protected function set_price( float $price ): void {
method set_price_currency (line 322) | protected function set_price_currency( string $price_currency ): void {
method set_images (line 333) | protected function set_images( array $images ): void {
method set_details (line 344) | protected function set_details( string $details ): void {
method set_url (line 355) | protected function set_url( string $url ): void {
method set_aggregate_rating (line 366) | protected function set_aggregate_rating( array $aggregate_rating ): vo...
FILE: includes/Shopping/Product_Meta.php
class Product_Meta (line 40) | class Product_Meta extends Service_Base implements HasMeta, PluginUninst...
method __construct (line 59) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 72) | public static function get_requirements(): array {
method register (line 81) | public function register(): void {
method register_meta (line 90) | public function register_meta(): void {
method on_plugin_uninstall (line 116) | public function on_plugin_uninstall(): void {
FILE: includes/Shopping/Shopify_Query.php
class Shopify_Query (line 82) | class Shopify_Query implements Product_Query {
method __construct (line 97) | public function __construct( Settings $settings ) {
method get_search (line 114) | public function get_search( string $search_term, int $page = 1, int $p...
method get_host (line 170) | protected function get_host(): string {
method get_access_token (line 187) | protected function get_access_token(): string {
method execute_query (line 205) | protected function execute_query( string $query ) {
method get_products_query (line 261) | protected function get_products_query( string $search_term, string $af...
method get_remote_products (line 320) | protected function get_remote_products( string $search_term, string $a...
method get_cache_key (line 400) | protected function get_cache_key( string $search_term, string $after, ...
method fetch_remote_products (line 421) | protected function fetch_remote_products( string $search_term, int $pa...
FILE: includes/Shopping/Shopping_Vendors.php
class Shopping_Vendors (line 39) | class Shopping_Vendors {
method __construct (line 55) | public function __construct( Injector $injector ) {
method get_vendor_class (line 66) | public function get_vendor_class( string $name ): ?Product_Query {
method get_vendors (line 89) | public function get_vendors(): array {
FILE: includes/Shopping/WooCommerce_Query.php
class WooCommerce_Query (line 40) | class WooCommerce_Query implements Product_Query {
method __construct (line 53) | public function __construct( WooCommerce $woocommerce ) {
method get_search (line 69) | public function get_search( string $search_term, int $page = 1, int $p...
method get_product_image_ids (line 164) | protected function get_product_image_ids( WC_Product $product ): array {
method get_product_image (line 179) | protected function get_product_image( int $image_id ): array {
FILE: includes/Shortcode/Embed_Shortcode.php
class Embed_Shortcode (line 36) | class Embed_Shortcode extends Embed_Base {
method register (line 47) | public function register(): void {
method render_shortcode (line 60) | public function render_shortcode( $attributes, ?string $content ): str...
FILE: includes/Shortcode/Stories_Shortcode.php
class Stories_Shortcode (line 40) | class Stories_Shortcode extends Service_Base {
method register (line 52) | public function register(): void {
method render_stories (line 67) | public function render_stories( $attrs ): string {
method prepare_story_attrs (line 118) | private function prepare_story_attrs( array $attributes ): array {
method prepare_story_args (line 143) | private function prepare_story_args( array $attributes ): array {
FILE: includes/Stories_Script_Data.php
class Stories_Script_Data (line 39) | class Stories_Script_Data {
method __construct (line 53) | public function __construct( Injector $injector ) {
method get_script_data (line 64) | public function get_script_data(): array {
method fields_states (line 93) | public function fields_states(): array {
method get_layouts (line 137) | public function get_layouts(): array {
FILE: includes/Story_Archive.php
class Story_Archive (line 38) | class Story_Archive extends Service_Base {
method __construct (line 63) | public function __construct( Settings $settings, Story_Post_Type $stor...
method register (line 73) | public function register(): void {
method redirect_post_type_archive_urls (line 96) | public function redirect_post_type_archive_urls( $bypass, WP_Query $qu...
method update_archive_setting (line 126) | public function update_archive_setting(): void {
method pre_get_posts (line 142) | public function pre_get_posts( WP_Query $query ): void {
method on_remove_archive_page (line 172) | public function on_remove_archive_page( int $postid ): void {
method filter_display_post_states (line 200) | public function filter_display_post_states( $post_states, ?WP_Post $po...
FILE: includes/Story_Post_Type.php
class Story_Post_Type (line 42) | class Story_Post_Type extends Post_Type_Base implements HasRequirements,...
method __construct (line 85) | public function __construct( Settings $settings ) {
method register (line 96) | public function register(): void {
method get_requirements (line 115) | public static function get_requirements(): array {
method get_slug (line 124) | public function get_slug(): string {
method register_meta (line 133) | public function register_meta(): void {
method bulk_post_updated_messages (line 202) | public function bulk_post_updated_messages( $bulk_messages, array $bul...
method change_default_title (line 235) | public function change_default_title( $data ) {
method filter_empty_content (line 259) | public function filter_empty_content( $maybe_empty, array $data ): bool {
method clear_user_posts_count (line 275) | public function clear_user_posts_count( int $post_id, WP_Post $post ):...
method get_has_archive (line 292) | public function get_has_archive() {
method on_plugin_uninstall (line 316) | public function on_plugin_uninstall(): void {
method get_args (line 333) | protected function get_args(): array {
method get_post_type_icon (line 406) | protected function get_post_type_icon(): string {
FILE: includes/Story_Query.php
class Story_Query (line 75) | class Story_Query {
method __construct (line 124) | public function __construct( array $story_attributes = [], array $quer...
method get_stories (line 145) | public function get_stories(): array {
method get_renderer (line 167) | public function get_renderer(): Renderer {
method render (line 192) | public function render(): string {
method get_story_attributes (line 207) | public function get_story_attributes(): array {
FILE: includes/Story_Revisions.php
class Story_Revisions (line 50) | class Story_Revisions extends Service_Base {
method __construct (line 72) | public function __construct( Story_Post_Type $story_post_type, Assets ...
method register (line 82) | public function register(): void {
method revisions_to_keep (line 99) | public function revisions_to_keep( $num ): int {
method filter_revision_fields (line 118) | public function filter_revision_fields( $fields, array $story ) {
method filter_revision_ui_diff (line 149) | public function filter_revision_ui_diff( $fields, $compare_from, WP_Po...
method enqueue_player_script (line 226) | public function enqueue_player_script(): void {
method get_story_player (line 254) | protected function get_story_player( WP_Post $post ): string {
FILE: includes/Taxonomy/Category_Taxonomy.php
class Category_Taxonomy (line 40) | class Category_Taxonomy extends Taxonomy_Base implements HasRequirements {
method __construct (line 46) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 60) | public static function get_requirements(): array {
method taxonomy_args (line 73) | protected function taxonomy_args(): array {
FILE: includes/Taxonomy/Tag_Taxonomy.php
class Tag_Taxonomy (line 40) | class Tag_Taxonomy extends Taxonomy_Base implements HasRequirements {
method __construct (line 46) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 60) | public static function get_requirements(): array {
method taxonomy_args (line 73) | protected function taxonomy_args(): array {
FILE: includes/Taxonomy/Taxonomy_Base.php
class Taxonomy_Base (line 80) | abstract class Taxonomy_Base extends Service_Base implements PluginActiv...
method register (line 109) | public function register(): void {
method register_taxonomy (line 118) | public function register_taxonomy(): void {
method unregister_taxonomy (line 127) | public function unregister_taxonomy(): void {
method on_site_initialization (line 138) | public function on_site_initialization( WP_Site $site ): void {
method on_plugin_activation (line 149) | public function on_plugin_activation( bool $network_wide ): void {
method on_plugin_deactivation (line 160) | public function on_plugin_deactivation( bool $network_wide ): void {
method get_taxonomy_slug (line 169) | public function get_taxonomy_slug(): string {
method on_plugin_uninstall (line 179) | public function on_plugin_uninstall(): void {
method taxonomy_args (line 208) | abstract protected function taxonomy_args(): array;
FILE: includes/Tracking.php
class Tracking (line 41) | class Tracking extends Service_Base {
method __construct (line 119) | public function __construct(
method register (line 144) | public function register(): void {
method get_registration_action (line 164) | public static function get_registration_action(): string {
method get_registration_action_priority (line 175) | public static function get_registration_action_priority(): int {
method enqueue_assets (line 186) | public function enqueue_assets( string $hook_suffix ): void {
method get_settings (line 204) | public function get_settings(): array {
method is_active (line 222) | public function is_active(): bool {
method get_user_properties (line 233) | private function get_user_properties(): array {
FILE: includes/User/Capabilities.php
class Capabilities (line 45) | class Capabilities implements Service, PluginActivationAware, SiteInitia...
method __construct (line 60) | public function __construct( Story_Post_Type $story_post_type ) {
method get_requirements (line 73) | public static function get_requirements(): array {
method on_plugin_activation (line 84) | public function on_plugin_activation( bool $network_wide ): void {
method on_site_initialization (line 95) | public function on_site_initialization( WP_Site $site ): void {
method on_site_removal (line 106) | public function on_site_removal( WP_Site $site ): void {
method on_plugin_uninstall (line 115) | public function on_plugin_uninstall(): void {
method add_caps_to_roles (line 127) | public function add_caps_to_roles(): void {
method remove_caps_from_roles (line 180) | public function remove_caps_from_roles(): void {
method get_all_capabilities (line 214) | protected function get_all_capabilities(): array {
FILE: includes/User/Preferences.php
class Preferences (line 40) | class Preferences extends Service_Base implements HasMeta, PluginUninsta...
method register (line 63) | public function register(): void {
method register_meta (line 72) | public function register_meta(): void {
method can_edit_current_user (line 127) | public function can_edit_current_user( bool $allowed, string $meta_key...
method get_preference (line 140) | public function get_preference( int $user_id, string $key ) {
method on_plugin_uninstall (line 149) | public function on_plugin_uninstall(): void {
FILE: includes/Widgets/Stories.php
class Stories (line 49) | class Stories extends WP_Widget {
method __construct (line 96) | public function __construct( Assets $assets, Story_Post_Type $story_po...
method widget (line 119) | public function widget( $args, $instance ): void {
method form (line 177) | public function form( $instance ): string {
method update (line 420) | public function update( $new_instance, $old_instance ): array {
method enqueue_scripts (line 449) | public function enqueue_scripts(): void {
method default_values (line 471) | private function default_values(): array {
method dropdown (line 498) | private function dropdown( array $args ): void {
method radio (line 544) | private function radio( array $args ): void {
method input (line 593) | private function input( array $args ): void {
method label (line 662) | private function label( array $args ): string {
FILE: includes/compat/Web_Stories_Compatibility.php
class Web_Stories_Compatibility (line 32) | class Web_Stories_Compatibility {
method __construct (line 86) | public function __construct( WP_Error $error ) { // phpcs:ignore Slevo...
method check_php_version (line 97) | public function check_php_version() {
method check_wp_version (line 119) | public function check_wp_version() {
method check_required_files (line 141) | public function check_required_files() {
method check_extensions (line 172) | public function check_extensions() {
method check_classes (line 208) | public function check_classes() {
method check_functions (line 252) | public function check_functions() {
method run_checks (line 298) | public function run_checks() {
method get_wp_version (line 314) | public function get_wp_version() {
method get_php_version (line 327) | public function get_php_version() {
method get_extensions (line 340) | public function get_extensions() {
method get_required_files (line 353) | public function get_required_files() {
method get_error (line 366) | public function get_error() {
method set_wp_version (line 380) | public function set_wp_version( $wp_version ) {
method set_php_version (line 394) | public function set_php_version( $php_version ) {
method set_extensions (line 408) | public function set_extensions( array $extensions ) {
method set_required_files (line 422) | public function set_required_files( array $required_files ) {
method add_to_error (line 434) | protected function add_to_error( $code, $message, $data = '' ) {
FILE: includes/compat/amp.php
function is_amp_endpoint (line 40) | function is_amp_endpoint(): bool {
function amp_is_request (line 57) | function amp_is_request(): bool {
FILE: includes/functions.php
function render_stories (line 40) | function render_stories( array $attrs = [], array $query_args = [] ): vo...
function get_stories (line 57) | function get_stories( array $attrs = [], array $query_args = [] ): array {
function render_theme_stories (line 66) | function render_theme_stories(): void {
FILE: includes/namespace.php
function activate (line 44) | function activate( ?bool $network_wide = false ): void {
function new_site (line 68) | function new_site( $site ): void {
function remove_site (line 94) | function remove_site( WP_Error $error, $site ): void {
function deactivate (line 119) | function deactivate( ?bool $network_wide = false ): void {
function load_amp_plugin_compat (line 143) | function load_amp_plugin_compat(): void {
function load_functions (line 154) | function load_functions(): void {
function rest_preload_api_request (line 178) | function rest_preload_api_request( array $memo, $path ): array {
function get_plugin_instance (line 251) | function get_plugin_instance(): Plugin {
function bootstrap_plugin (line 260) | function bootstrap_plugin(): void {
FILE: includes/polyfills/mbstring.php
function mb_convert_encoding (line 18) | function mb_convert_encoding( $s, $to, $from = null ) {
function mb_decode_mimeheader (line 23) | function mb_decode_mimeheader( $s ) {
function mb_encode_mimeheader (line 28) | function mb_encode_mimeheader( $s, $charset = null, $transferEnc = null,...
function mb_decode_numericentity (line 33) | function mb_decode_numericentity( $s, $convmap, $enc = null ) {
function mb_encode_numericentity (line 38) | function mb_encode_numericentity( $s, $convmap, $enc = null, $is_hex = f...
function mb_convert_case (line 43) | function mb_convert_case( $s, $mode, $enc = null ) {
function mb_internal_encoding (line 48) | function mb_internal_encoding( $enc = null ) {
function mb_language (line 53) | function mb_language( $lang = null ) {
function mb_list_encodings (line 58) | function mb_list_encodings() {
function mb_encoding_aliases (line 63) | function mb_encoding_aliases( $encoding ) {
function mb_check_encoding (line 68) | function mb_check_encoding( $var = null, $encoding = null ) {
function mb_detect_encoding (line 73) | function mb_detect_encoding( $str, $encodingList = null, $strict = false...
function mb_detect_order (line 78) | function mb_detect_order( $encodingList = null ) {
function mb_parse_str (line 83) | function mb_parse_str( $s, &$result = [] ) {
function mb_strlen (line 88) | function mb_strlen( $s, $enc = null ) {
function mb_strpos (line 93) | function mb_strpos( $s, $needle, $offset = 0, $enc = null ) {
function mb_strtolower (line 98) | function mb_strtolower( $s, $enc = null ) {
function mb_strtoupper (line 103) | function mb_strtoupper( $s, $enc = null ) {
function mb_substitute_character (line 108) | function mb_substitute_character( $char = null ) {
function mb_substr (line 113) | function mb_substr( $s, $start, $length = 2147483647, $enc = null ) {
function mb_stripos (line 118) | function mb_stripos( $s, $needle, $offset = 0, $enc = null ) {
function mb_stristr (line 123) | function mb_stristr( $s, $needle, $part = false, $enc = null ) {
function mb_strrchr (line 128) | function mb_strrchr( $s, $needle, $part = false, $enc = null ) {
function mb_strrichr (line 133) | function mb_strrichr( $s, $needle, $part = false, $enc = null ) {
function mb_strripos (line 138) | function mb_strripos( $s, $needle, $offset = 0, $enc = null ) {
function mb_strrpos (line 143) | function mb_strrpos( $s, $needle, $offset = 0, $enc = null ) {
function mb_strstr (line 148) | function mb_strstr( $s, $needle, $part = false, $enc = null ) {
function mb_get_info (line 153) | function mb_get_info( $type = 'all' ) {
function mb_http_output (line 158) | function mb_http_output( $enc = null ) {
function mb_strwidth (line 163) | function mb_strwidth( $s, $enc = null ) {
function mb_substr_count (line 168) | function mb_substr_count( $haystack, $needle, $enc = null ) {
function mb_output_handler (line 173) | function mb_output_handler( $contents, $status ) {
function mb_http_input (line 178) | function mb_http_input( $type = '' ) {
function mb_convert_variables (line 183) | function mb_convert_variables( $toEncoding, $fromEncoding, &$a = null, &...
function mb_ord (line 188) | function mb_ord( $s, $enc = null ) {
function mb_chr (line 193) | function mb_chr( $code, $enc = null ) {
function mb_scrub (line 198) | function mb_scrub( $s, $enc = null ) {
function mb_str_split (line 204) | function mb_str_split( $string, $split_length = 1, $encoding = null ) {
FILE: karma-dashboard.config.cjs
function getViewport (line 207) | function getViewport(flag) {
FILE: karma-story-editor.config.cjs
function getViewport (line 249) | function getViewport(flag) {
FILE: packages/activation-notice/src/app/components/dismiss.tsx
function Dismiss (line 30) | function Dismiss() {
FILE: packages/activation-notice/src/app/components/image.tsx
type ImgProps (line 27) | interface ImgProps {
type ImageProps (line 31) | interface ImageProps {
function Image (line 43) | function Image({ name, name2x, ...props }: ImageProps) {
FILE: packages/activation-notice/src/app/components/messageContent.tsx
function MessageContent (line 73) | function MessageContent() {
FILE: packages/activation-notice/src/app/components/paragraph.tsx
type ParagraphProps (line 22) | interface ParagraphProps {
FILE: packages/activation-notice/src/app/components/step1.tsx
function Step1 (line 61) | function Step1() {
FILE: packages/activation-notice/src/app/components/step2.tsx
function Step2 (line 56) | function Step2() {
FILE: packages/activation-notice/src/app/components/step3.tsx
function Step3 (line 55) | function Step3() {
FILE: packages/activation-notice/src/app/components/successMessage.tsx
function SuccessMessage (line 81) | function SuccessMessage() {
FILE: packages/activation-notice/src/app/components/test/step1.js
function render (line 30) | function render() {
FILE: packages/activation-notice/src/app/components/test/step2.js
function render (line 30) | function render() {
FILE: packages/activation-notice/src/app/components/test/step3.js
function render (line 30) | function render() {
FILE: packages/activation-notice/src/app/components/test/successMessage.js
function render (line 30) | function render() {
FILE: packages/activation-notice/src/app/config/configProvider.tsx
type ConfigProviderProps (line 27) | interface ConfigProviderProps {
function ConfigProvider (line 32) | function ConfigProvider({ config, children }: ConfigProviderProps) {
FILE: packages/activation-notice/src/app/config/context.ts
constant INITIAL_STATE (line 22) | const INITIAL_STATE = {};
type ContextState (line 24) | interface ContextState {
FILE: packages/activation-notice/src/app/config/useConfig.ts
function useConfig (line 27) | function useConfig(): ContextState {
FILE: packages/activation-notice/src/app/index.tsx
type AppProps (line 33) | interface AppProps {
function App (line 37) | function App({ config }: AppProps) {
FILE: packages/activation-notice/src/index.tsx
type ActivationNoticeSettings (line 34) | interface ActivationNoticeSettings {
type Window (line 44) | interface Window {
FILE: packages/activation-notice/src/theme.ts
function useTheme (line 35) | function useTheme(): DefaultTheme {
FILE: packages/activation-notice/src/typings/styled-components.d.ts
type Font (line 19) | interface Font {
type DefaultTheme (line 27) | interface DefaultTheme {
FILE: packages/animation/src/components/AMPAnimations.tsx
function AMPAnimations (line 22) | function AMPAnimations() {
FILE: packages/animation/src/components/AMPKeyframes.tsx
function AMPKeyframes (line 29) | function AMPKeyframes() {
FILE: packages/animation/src/components/AMPWrapper.tsx
type ComposableWrapperProps (line 39) | type ComposableWrapperProps = PropsWithChildren<{
type Composed (line 43) | type Composed = PropsWithChildren<unknown>;
function ComposableWrapper (line 45) | function ComposableWrapper({
function AMPWrapper (line 75) | function AMPWrapper({ target, children }: WrapperProps) {
FILE: packages/animation/src/components/WAAPIWrapper.tsx
function WAAPIAnimationWrapper (line 29) | function WAAPIAnimationWrapper({
function WAAPIWrapper (line 57) | function WAAPIWrapper({ children, target }: WrapperProps) {
FILE: packages/animation/src/components/animationMachine.ts
function useAnimationMachine (line 46) | function useAnimationMachine() {
FILE: packages/animation/src/components/generateKeyframesMap.ts
function generateKeyframesMap (line 22) | function generateKeyframesMap(
FILE: packages/animation/src/components/provider.tsx
constant STABLE (line 64) | const STABLE: unknown[] = [];
function mapHasReferentialEntry (line 66) | function mapHasReferentialEntry<K, V>(
function Provider (line 73) | function Provider({
FILE: packages/animation/src/components/stories/index.js
function ColorSquare (line 34) | function ColorSquare({ color, ...rest }) {
function SquareWrapper (line 53) | function SquareWrapper({ children }) {
FILE: packages/animation/src/components/test/WAAPIWrapper.tsx
type Tracker (line 32) | type Tracker = FunctionComponent<{ target: string }>;
type TrackersProps (line 33) | type TrackersProps = {
type ElementsWithWrapperProps (line 37) | type ElementsWithWrapperProps = {
function Trackers (line 43) | function Trackers({
FILE: packages/animation/src/components/test/animationProvider.tsx
function flushPromiseQueue (line 45) | function flushPromiseQueue() {
function createWrapperWithProps (line 49) | function createWrapperWithProps<T>(
type MockAnimation (line 64) | type MockAnimation = Animation & {
FILE: packages/animation/src/components/test/generateKeyframesMap.ts
type AnimationParts (line 24) | type AnimationParts = Record<string, AnimationPart[]>;
FILE: packages/animation/src/components/types.ts
type ElementAnimationHoister (line 40) | type ElementAnimationHoister = (
type AnimationHoister (line 44) | type AnimationHoister = (animation: Animation) => () => void;
type AnimationProviderState (line 46) | interface AnimationProviderState {
type AnimationProviderProps (line 63) | type AnimationProviderProps = PropsWithChildren<{
type StoryAnimationMap (line 70) | type StoryAnimationMap = Map<StoryAnimation['id'], StoryAnimation>;
type ElementAnimationPartsMap (line 71) | type ElementAnimationPartsMap = Map<ElementId, AnimationPart[]>;
type WAAPIElementAnimation (line 73) | interface WAAPIElementAnimation {
type WAAPIElementAnimationMap (line 77) | type WAAPIElementAnimationMap = Map<symbol, WAAPIElementAnimation>;
type ElementMap (line 78) | type ElementMap = Map<ElementId, Element>;
type WAAPIAnimationWrapperProps (line 80) | type WAAPIAnimationWrapperProps = PropsWithChildren<{
type WrapperProps (line 87) | type WrapperProps = PropsWithChildren<{
type AnimationMachineState (line 91) | enum AnimationMachineState {
type AnimationMachineTransition (line 96) | enum AnimationMachineTransition {
FILE: packages/animation/src/components/useStoryAnimationContext.ts
function useStoryAnimationContext (line 30) | function useStoryAnimationContext<T>(
FILE: packages/animation/src/constants.ts
constant BEZIER (line 27) | const BEZIER = {
type BezierType (line 56) | type BezierType = keyof typeof BEZIER;
constant ANIMATION_EFFECTS (line 58) | const ANIMATION_EFFECTS = {
constant BACKGROUND_ANIMATION_EFFECTS (line 97) | const BACKGROUND_ANIMATION_EFFECTS = {
constant ANIMATION_PARTS (line 112) | const ANIMATION_PARTS = {
constant SCALE_DIRECTIONS (line 151) | const SCALE_DIRECTIONS = {
constant BG_MIN_SCALE (line 156) | const BG_MIN_SCALE = 100;
constant BG_MAX_SCALE (line 157) | const BG_MAX_SCALE = 400;
FILE: packages/animation/src/outputs/animationOutput.tsx
function AnimationOutput (line 22) | function AnimationOutput({ config }: AnimationOutputProps) {
FILE: packages/animation/src/outputs/keyframesOutput.tsx
function KeyframesOutput (line 22) | function KeyframesOutput({ id, keyframes, ...options }: KeyframesOutputP...
FILE: packages/animation/src/outputs/output.tsx
function WithAnimation (line 22) | function WithAnimation({
FILE: packages/animation/src/outputs/types.ts
type AnimationConfig (line 27) | interface AnimationConfig extends AMPEffectTiming {
type AnimationOutputProps (line 33) | interface AnimationOutputProps {
type WithAnimationProps (line 37) | type WithAnimationProps = PropsWithChildren<{
type KeyframesOutputProps (line 45) | interface KeyframesOutputProps extends AMPEffectTiming {
FILE: packages/animation/src/parts/createAnimation.tsx
function createAnimation (line 32) | function createAnimation<T extends Keyframes>(
FILE: packages/animation/src/parts/createAnimationPart.ts
function convertEasingPreset (line 53) | function convertEasingPreset({
function createAnimationPart (line 65) | function createAnimationPart(
FILE: packages/animation/src/parts/effects/backgroundPan.ts
type PanBackgroundEffect (line 35) | interface PanBackgroundEffect extends AMPEffectTiming {
function EffectBackgroundPan (line 40) | function EffectBackgroundPan(
FILE: packages/animation/src/parts/effects/backgroundPanAndZoom.ts
type PanAndZoomBackgroundEffect (line 38) | interface PanAndZoomBackgroundEffect extends AMPEffectTiming {
function EffectBackgroundPanAndZoom (line 44) | function EffectBackgroundPanAndZoom(
FILE: packages/animation/src/parts/effects/backgroundZoom.ts
type TransformOrigin (line 37) | type TransformOrigin = {
type ZoomBackgroundEffect (line 42) | interface ZoomBackgroundEffect extends AMPEffectTiming {
function EffectBackgroundZoom (line 48) | function EffectBackgroundZoom(
FILE: packages/animation/src/parts/effects/drop.ts
function getMinTopOffset (line 36) | function getMinTopOffset(element: DimensionableElement) {
function getDropKeyframes (line 40) | function getDropKeyframes(element: DimensionableElement): Keyframes {
type DropEffect (line 99) | interface DropEffect extends AMPEffectTiming {
function EffectDrop (line 103) | function EffectDrop(
FILE: packages/animation/src/parts/effects/fadeIn.ts
type FadeInEffect (line 28) | interface FadeInEffect extends AMPEffectTiming {
function EffectFadeIn (line 31) | function EffectFadeIn({
FILE: packages/animation/src/parts/effects/flyIn.tsx
type FlyInEffect (line 38) | interface FlyInEffect extends AMPEffectTiming {
function EffectFlyIn (line 43) | function EffectFlyIn(
FILE: packages/animation/src/parts/effects/pan.ts
function getTargetScale (line 41) | function getTargetScale({ width, height }: ElementBox) {
type PanEffect (line 55) | interface PanEffect extends AMPEffectTiming {
function EffectPan (line 60) | function EffectPan(
FILE: packages/animation/src/parts/effects/pulse.ts
type PulseEffect (line 28) | interface PulseEffect extends AMPEffectTiming {
function EffectPulse (line 33) | function EffectPulse({
FILE: packages/animation/src/parts/effects/rotateIn.tsx
type RotateInEffect (line 42) | interface RotateInEffect extends AMPEffectTiming {
function EffectRotateIn (line 47) | function EffectRotateIn(
FILE: packages/animation/src/parts/effects/stories/pan.js
constant SAMPLE_SRC_1 (line 36) | const SAMPLE_SRC_1 = 'https://picsum.photos/1120/746?image=1025';
FILE: packages/animation/src/parts/effects/twirlIn.tsx
type TwirlInEffect (line 32) | interface TwirlInEffect extends AMPEffectTiming {
function EffectTwirlIn (line 36) | function EffectTwirlIn(
FILE: packages/animation/src/parts/effects/whooshIn.tsx
type WhooshInEffect (line 40) | interface WhooshInEffect extends AMPEffectTiming {
function EffectWhooshIn (line 45) | function EffectWhooshIn(
FILE: packages/animation/src/parts/effects/zoom.tsx
type ZoomEffect (line 36) | interface ZoomEffect extends AMPEffectTiming {
function EffectZoom (line 41) | function EffectZoom({
FILE: packages/animation/src/parts/emptyAnimationPart.tsx
function EmptyAMPTarget (line 27) | function EmptyAMPTarget({
function emptyAnimationPart (line 34) | function emptyAnimationPart(): AnimationPart {
FILE: packages/animation/src/parts/getAnimationEffectFields.ts
function getAnimationEffectFields (line 37) | function getAnimationEffectFields(type?: AnimationType) {
function getAnimationEffectDefaults (line 82) | function getAnimationEffectDefaults(type: AnimationType) {
FILE: packages/animation/src/parts/simple/blinkOn.ts
constant DEFAULT_BLINKS (line 29) | const DEFAULT_BLINKS = 10;
constant AVAILABLE_OPACITY (line 30) | const AVAILABLE_OPACITY = [0, 0.25, 0.75, 1];
function range (line 34) | function range(i: number) {
function generateOpacityFrames (line 40) | function generateOpacityFrames(blinkCount: number = DEFAULT_BLINKS) {
type BlinkOnAnimation (line 55) | interface BlinkOnAnimation extends AMPEffectTiming {
function AnimationBlinkOn (line 60) | function AnimationBlinkOn({
FILE: packages/animation/src/parts/simple/bounce.ts
type BounceAnimation (line 45) | interface BounceAnimation extends AMPEffectTiming {
function AnimationBounce (line 49) | function AnimationBounce({ type, ...args }: BounceAnimation) {
FILE: packages/animation/src/parts/simple/fade.ts
type FadeAnimation (line 32) | interface FadeAnimation extends AMPEffectTiming {
function AnimationFade (line 38) | function AnimationFade({
FILE: packages/animation/src/parts/simple/flip.ts
type FlipAnimation (line 58) | interface FlipAnimation extends AMPEffectTiming {
function AnimationFlip (line 64) | function AnimationFlip({
FILE: packages/animation/src/parts/simple/floatOn.ts
type FloatOnAnimation (line 48) | interface FloatOnAnimation extends AMPEffectTiming {
function AnimationFloatOn (line 53) | function AnimationFloatOn({
FILE: packages/animation/src/parts/simple/move.ts
type MoveAnimation (line 31) | interface MoveAnimation extends AMPEffectTiming {
function AnimationMove (line 38) | function AnimationMove(
FILE: packages/animation/src/parts/simple/pulse.ts
function generatePulseKeyframes (line 23) | function generatePulseKeyframes(scale: number) {
type PulseAnimation (line 40) | interface PulseAnimation extends AMPEffectTiming {
function AnimationPulse (line 45) | function AnimationPulse({
FILE: packages/animation/src/parts/simple/spin.ts
type SpinAnimation (line 31) | interface SpinAnimation extends AMPEffectTiming {
function AnimationSpin (line 37) | function AnimationSpin(
FILE: packages/animation/src/parts/simple/zoom.ts
type ZoomAnimation (line 29) | interface ZoomAnimation extends AMPEffectTiming {
function AnimationZoom (line 40) | function AnimationZoom({
FILE: packages/animation/src/parts/types.ts
type AMPAnimationProps (line 32) | type AMPAnimationProps = PropsWithChildren<{
type WAAPIAnimation (line 38) | interface WAAPIAnimation {
type AnimationPart (line 51) | interface AnimationPart<T extends Keyframes = Keyframes> {
FILE: packages/animation/src/storybookUtils/index.js
constant AMP_STORY_ASPECT_RATIO (line 28) | const AMP_STORY_ASPECT_RATIO = `${PAGE_WIDTH}:${PAGE_HEIGHT}`;
function AMPStoryWrapper (line 30) | function AMPStoryWrapper({ children }) {
FILE: packages/animation/src/storybookUtils/utils/ampBoilerplate.js
function Boilerplate (line 24) | function Boilerplate() {
FILE: packages/animation/src/types/animation.ts
type AnimationType (line 46) | enum AnimationType {
type ZoomDirection (line 80) | type ZoomDirection =
type AnimationDirection (line 89) | enum AnimationDirection {
type AnimationInput (line 96) | type AnimationInput =
type AnimationInputWithPreset (line 119) | type AnimationInputWithPreset = AnimationInput & {
type StoryAnimation (line 126) | type StoryAnimation = AnimationInputWithPreset & {
FILE: packages/animation/src/types/effects.ts
type ScaleDirection (line 17) | enum ScaleDirection {
type Rotation (line 27) | enum Rotation {
type Axis (line 33) | enum Axis {
type FieldType (line 38) | enum FieldType {
type AMPEffectTiming (line 50) | interface AMPEffectTiming extends Omit<
FILE: packages/animation/src/types/element.ts
type ElementId (line 22) | type ElementId = string;
type Element (line 24) | interface Element extends DimensionableElement {
type ScaledElement (line 29) | interface ScaledElement extends Element {
function isScaledElement (line 33) | function isScaledElement(e: Element): e is ScaledElement {
FILE: packages/animation/src/types/keyframes.ts
type Keyframes (line 17) | type Keyframes = Keyframe[] | PropertyIndexedKeyframes;
FILE: packages/animation/src/types/storyAnimationState.ts
type StoryAnimationState (line 17) | enum StoryAnimationState {
FILE: packages/animation/src/typings/global.d.ts
type IntrinsicElements (line 24) | interface IntrinsicElements {
FILE: packages/animation/src/utils/createKeyframeEffect.ts
function createKeyframeEffect (line 22) | function createKeyframeEffect(
FILE: packages/animation/src/utils/generateLookupMap.ts
function generateLookupMap (line 17) | function generateLookupMap(values: number[]) {
FILE: packages/animation/src/utils/getElementOffsets.ts
type MediaElement (line 40) | interface MediaElement extends ScaledElement {
constant PRECISION (line 46) | const PRECISION = 1;
function isMediaElement (line 48) | function isMediaElement(e: DimensionableElement): e is MediaElement {
function getElementOffsets (line 52) | function getElementOffsets(element: DimensionableElement) {
constant DEFAULT_HAS_OFFSETS (line 81) | const DEFAULT_HAS_OFFSETS = {
function getHasElementOffsets (line 88) | function getHasElementOffsets(element: DimensionableElement) {
function getElementOrigin (line 107) | function getElementOrigin(
FILE: packages/animation/src/utils/getGlobalSpace.ts
type Stringable (line 22) | type Stringable = string | number | boolean | null | undefined;
type ElementWithRotation (line 23) | type ElementWithRotation = Partial<Pick<Element, 'rotationAngle'>>;
function literal (line 37) | function literal(
function getGlobalSpace (line 63) | function getGlobalSpace(element: ElementWithRotation = {}) {
FILE: packages/animation/src/utils/getInitialStyleFromKeyframes.ts
constant ALLOWLIST (line 22) | const ALLOWLIST = ['opacity', 'transform'];
type CSSProperty (line 24) | type CSSProperty = string | number | null | undefined;
type CSSVariables (line 25) | interface CSSVariables {
function getInitialStyleFromKeyframes (line 37) | function getInitialStyleFromKeyframes(keyframes: Keyframes) {
FILE: packages/animation/src/utils/getOffPageOffset.ts
function calcTopOffset (line 27) | function calcTopOffset(box: ElementBox, dangerZoneOffset: number): number {
function calcBottomOffset (line 33) | function calcBottomOffset(box: ElementBox, dangerZoneOffset: number): nu...
function calcLeftOffset (line 39) | function calcLeftOffset(box: ElementBox): number {
function calcRightOffset (line 44) | function calcRightOffset(box: ElementBox): number {
function getOffPageOffset (line 50) | function getOffPageOffset(element: DimensionableElement) {
FILE: packages/animation/src/utils/getTotalDuration.ts
function getTotalDuration (line 22) | function getTotalDuration(animations: StoryAnimation[] = []) {
FILE: packages/animation/src/utils/orderByKeys.ts
function orderByKeys (line 31) | function orderByKeys<T>(
FILE: packages/animation/src/utils/padArray.ts
function padArray (line 17) | function padArray(values: number[], padCount: number) {
FILE: packages/animation/src/utils/sanitizeTimings.ts
function sanitizeTimings (line 22) | function sanitizeTimings({
FILE: packages/animation/src/utils/test/getTotalDuration.ts
constant BASE_ANIMATION (line 23) | const BASE_ANIMATION = {
FILE: packages/commander/src/index.ts
constant PLUGIN_DIR (line 38) | const PLUGIN_DIR = process.cwd();
constant PLUGIN_FILE (line 39) | const PLUGIN_FILE = 'web-stories.php';
constant BUILD_DIR (line 40) | const BUILD_DIR = 'build/web-stories';
FILE: packages/commander/src/utils/appendRevisionToVersion.ts
function appendRevisionToVersion (line 32) | function appendRevisionToVersion(version: string): string {
FILE: packages/commander/src/utils/bundlePlugin.ts
function bundlePlugin (line 38) | function bundlePlugin(
FILE: packages/commander/src/utils/copyFiles.ts
function copyFiles (line 29) | function copyFiles(source: string, target: string, ignoredFiles: string[...
FILE: packages/commander/src/utils/createBuild.ts
function createBuild (line 30) | function createBuild(source: string, target: string, composer = false) {
FILE: packages/commander/src/utils/deleteExistingZipFiles.ts
function deleteExistingZipFiles (line 27) | function deleteExistingZipFiles(buildDir: string) {
FILE: packages/commander/src/utils/generateZipFile.ts
function generateZipFile (line 32) | function generateZipFile(source: string, zipName: string) {
FILE: packages/commander/src/utils/getCurrentVersionNumber.ts
constant VERSION_REGEX (line 22) | const VERSION_REGEX = /\* Version:(.+)/;
constant VERSION_CONSTANT_REGEX (line 23) | const VERSION_CONSTANT_REGEX =
function getCurrentVersionNumber (line 33) | function getCurrentVersionNumber(pluginFile: string, constant = false): ...
FILE: packages/commander/src/utils/getIgnoredFiles.ts
function getIgnoredFiles (line 28) | function getIgnoredFiles(source: string): string[] {
FILE: packages/commander/src/utils/resizeSvgPath.ts
function resizeSvgPath (line 17) | function resizeSvgPath(x: number, y: number, path: string) {
FILE: packages/commander/src/utils/test/getCurrentVersionNumber.js
constant PLUGIN_FILE_CONTENT (line 29) | const PLUGIN_FILE_CONTENT = `
FILE: packages/commander/src/utils/test/updateCdnUrl.js
constant PLUGIN_FILE_CONTENT (line 29) | const PLUGIN_FILE_CONTENT = `
FILE: packages/commander/src/utils/test/updateVersionNumbers.js
constant PLUGIN_FILE_CONTENT (line 32) | const PLUGIN_FILE_CONTENT = `
FILE: packages/commander/src/utils/updateCdnUrl.ts
constant CDN_BASE_URL (line 22) | const CDN_BASE_URL = 'https://wp.stories.google/static/';
constant CDN_URL_CONSTANT_REGEX (line 23) | const CDN_URL_CONSTANT_REGEX =
function updateCdnURL (line 34) | function updateCdnURL(pluginFile: string, version: string | number) {
FILE: packages/commander/src/utils/updateVersionNumbers.ts
constant VERSION_REGEX (line 27) | const VERSION_REGEX = /\* Version:(.+)/;
constant VERSION_CONSTANT_REGEX (line 28) | const VERSION_CONSTANT_REGEX =
function updateVersionNumbers (line 43) | function updateVersionNumbers(
FILE: packages/dashboard/src/app/api/apiProvider.js
function ApiProvider (line 31) | function ApiProvider({ children }) {
FILE: packages/dashboard/src/app/api/useApi.js
function useApi (line 27) | function useApi(selector = identity) {
FILE: packages/dashboard/src/app/api/useApiAlerts.js
function useApiAlerts (line 27) | function useApiAlerts() {
FILE: packages/dashboard/src/app/api/useStoryApi.js
constant DRAFT_STORAGE_KEY (line 46) | const DRAFT_STORAGE_KEY = `${SESSION_STORAGE_PREFIX.LOCAL_AUTOSAVE_PREFI...
FILE: packages/dashboard/src/app/api/useTaxonomyApi.js
function useTaxonomyApi (line 21) | function useTaxonomyApi() {
FILE: packages/dashboard/src/app/api/useUsersApi.js
function useUsersApi (line 21) | function useUsersApi() {
FILE: packages/dashboard/src/app/config/configProvider.tsx
type ConfigProviderProps (line 28) | interface ConfigProviderProps {
function ConfigProvider (line 32) | function ConfigProvider({ config, children }: ConfigProviderProps) {
FILE: packages/dashboard/src/app/config/useConfig.ts
function useConfig (line 28) | function useConfig<T>(
FILE: packages/dashboard/src/app/reducer/story/constants.js
constant ACTION_TYPES (line 16) | const ACTION_TYPES = {
FILE: packages/dashboard/src/app/reducer/story/storyReducer.js
function storyReducer (line 23) | function storyReducer(state, action) {
FILE: packages/dashboard/src/app/reducer/templates/constants.js
constant ACTION_TYPES (line 17) | const ACTION_TYPES = {
FILE: packages/dashboard/src/app/reducer/templates/templateReducer.js
function templateReducer (line 23) | function templateReducer(state, action) {
FILE: packages/dashboard/src/app/router/route.ts
function parentRoute (line 22) | function parentRoute() {
function resolveRoute (line 34) | function resolveRoute(route: string) {
type MatchPathProps (line 65) | interface MatchPathProps {
function matchPath (line 73) | function matchPath({
type RouteProps (line 111) | interface RouteProps {
function Route (line 117) | function Route({
FILE: packages/dashboard/src/app/router/routerProvider.tsx
type ActiveRouteProps (line 31) | interface ActiveRouteProps {
function RouterProvider (line 48) | function RouterProvider({
FILE: packages/dashboard/src/app/router/test/routerProvider.js
constant DEFAULT_ROUTE (line 27) | const DEFAULT_ROUTE = '/';
constant ROUTE_LIST (line 28) | const ROUTE_LIST = ['/templates-gallery', '/settings', '/custom-route'];
constant AVAILABLE_ROUTES (line 29) | const AVAILABLE_ROUTES = [...ROUTE_LIST, DEFAULT_ROUTE];
FILE: packages/dashboard/src/app/router/useRouteHistory.ts
function useRouteHistory (line 30) | function useRouteHistory<T>(
FILE: packages/dashboard/src/app/serializers/templates.js
function reshapeTemplateObject (line 22) | function reshapeTemplateObject(
FILE: packages/dashboard/src/app/textContent/index.js
constant ERRORS (line 22) | const ERRORS = {
FILE: packages/dashboard/src/app/views/constants.js
constant TEMPLATE_META_DATA_TYPES (line 16) | const TEMPLATE_META_DATA_TYPES = {
FILE: packages/dashboard/src/app/views/exploreTemplates/content/index.js
function Content (line 53) | function Content({
FILE: packages/dashboard/src/app/views/exploreTemplates/content/templateGridItem.js
constant FOCUS_TEMPLATE_CLASS (line 47) | const FOCUS_TEMPLATE_CLASS = 'focus_template';
FILE: packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js
function TemplateGridView (line 43) | function TemplateGridView({
FILE: packages/dashboard/src/app/views/exploreTemplates/filters/TemplateFiltersProvider/index.js
function TemplateFiltersProvider (line 43) | function TemplateFiltersProvider({ children }) {
FILE: packages/dashboard/src/app/views/exploreTemplates/filters/useTemplateFilters.js
function useTemplateFilters (line 26) | function useTemplateFilters(selector = identity) {
FILE: packages/dashboard/src/app/views/exploreTemplates/header/index.js
function Header (line 49) | function Header({ isLoading, totalTemplates, view, searchOptions = [] }) {
FILE: packages/dashboard/src/app/views/exploreTemplates/index.js
function ExploreTemplatesView (line 49) | function ExploreTemplatesView() {
function ExploreTemplates (line 293) | function ExploreTemplates() {
FILE: packages/dashboard/src/app/views/exploreTemplates/karma/exploreTemplates.karma.js
function navigateToExploreTemplates (line 43) | function navigateToExploreTemplates() {
function getTemplateElementById (line 52) | function getTemplateElementById(id) {
function getTemplatesState (line 58) | async function getTemplatesState() {
function focusOnGridByKeyboard (line 65) | async function focusOnGridByKeyboard() {
function getTemplateIdByTitle (line 171) | async function getTemplateIdByTitle(title) {
FILE: packages/dashboard/src/app/views/exploreTemplates/modal/index.js
function TemplateDetailsModal (line 35) | function TemplateDetailsModal({
FILE: packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/content/index.js
function DetailsContent (line 91) | function DetailsContent({
FILE: packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/header/index.js
function Header (line 50) | function Header({
FILE: packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/karma/templateDetails.karma.js
function navigateToFirstTemplate (line 43) | async function navigateToFirstTemplate() {
function getTemplateElementById (line 66) | function getTemplateElementById(id) {
function focusOnCardGallery (line 70) | async function focusOnCardGallery() {
function getTemplatesState (line 85) | async function getTemplatesState() {
function getTemplateTitle (line 92) | async function getTemplateTitle(index) {
function expectModalClose (line 97) | async function expectModalClose() {
FILE: packages/dashboard/src/app/views/exploreTemplates/templateFilters.js
function updateSelectedItems (line 28) | function updateSelectedItems(items, setter) {
function clearAllSelectedItems (line 41) | function clearAllSelectedItems(items, setter) {
function useTemplateFilters (line 51) | function useTemplateFilters() {
FILE: packages/dashboard/src/app/views/filters/types.js
constant UPDATE_FILTER (line 17) | const UPDATE_FILTER = 'UPDATE_FILTER';
constant UPDATE_SORT (line 18) | const UPDATE_SORT = 'UPDATE_SORT';
constant REGISTER_FILTERS (line 19) | const REGISTER_FILTERS = 'REGISTER_FILTERS';
FILE: packages/dashboard/src/app/views/myStories/content/index.js
function NoAvailableContent (line 46) | function NoAvailableContent({ filtersObject }) {
function Content (line 64) | function Content({
FILE: packages/dashboard/src/app/views/myStories/content/listView/index.js
function StoryListView (line 65) | function StoryListView({
FILE: packages/dashboard/src/app/views/myStories/content/stories/index.js
function forceUniqueIds (line 37) | function forceUniqueIds(stories) {
FILE: packages/dashboard/src/app/views/myStories/content/storiesView/index.js
constant ACTIVE_DIALOG_DELETE_STORY (line 57) | const ACTIVE_DIALOG_DELETE_STORY = 'DELETE_STORY';
function StoriesView (line 58) | function StoriesView({ loading, storyActions, stories, view }) {
FILE: packages/dashboard/src/app/views/myStories/content/storyListItem/index.js
function onFocusSelectAll (line 54) | function onFocusSelectAll(e) {
function onBlurDeselectAll (line 58) | function onBlurDeselectAll() {
FILE: packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/author/useAuthorFilter.js
function useAuthorFilter (line 37) | function useAuthorFilter() {
FILE: packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/index.js
function StoryFiltersProvider (line 60) | function StoryFiltersProvider({ children }) {
FILE: packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/taxonomy/useTaxonomyFilters.js
function useTaxonomyFilters (line 36) | function useTaxonomyFilters() {
FILE: packages/dashboard/src/app/views/myStories/filters/useStoryFilters.js
function useStoryFilters (line 26) | function useStoryFilters(selector = identity) {
FILE: packages/dashboard/src/app/views/myStories/header/index.js
function Header (line 50) | function Header({ initialPageReady, stories, totalStoriesByStatus, view ...
FILE: packages/dashboard/src/app/views/myStories/header/storyStatusToggle.js
function StoryStatusToggle (line 44) | function StoryStatusToggle({
FILE: packages/dashboard/src/app/views/myStories/index.js
function MyStoriesView (line 34) | function MyStoriesView() {
function MyStories (line 148) | function MyStories() {
FILE: packages/dashboard/src/app/views/myStories/karma/myStories.karma.js
function getStoriesState (line 48) | async function getStoriesState() {
function focusOnGridByKeyboard (line 56) | async function focusOnGridByKeyboard() {
function getContextMenuItem (line 71) | async function getContextMenuItem(contextMenuText, storyIndex = 0) {
FILE: packages/dashboard/src/app/views/myStories/karma/myStoriesList.karma.js
function getStoriesState (line 47) | async function getStoriesState() {
function isElementVisible (line 55) | function isElementVisible(element) {
FILE: packages/dashboard/src/app/views/shared/bodyViewOptions.js
constant FILTER_MAX_WIDTH (line 36) | const FILTER_MAX_WIDTH = 350;
function BodyViewOptions (line 66) | function BodyViewOptions({
FILE: packages/dashboard/src/app/views/shared/emptyContentMessage.js
function EmptyContentMessage (line 46) | function EmptyContentMessage({ children }) {
FILE: packages/dashboard/src/app/views/shared/sortDropDown.js
function SortDropDown (line 35) | function SortDropDown({
FILE: packages/dashboard/src/app/views/utils/composeTemplateFilter.js
function composeTemplateFilter (line 30) | function composeTemplateFilter(filters) {
FILE: packages/dashboard/src/app/views/utils/getSearchOptions.js
function getSearchOptions (line 17) | function getSearchOptions(options) {
FILE: packages/dashboard/src/app/views/utils/getTemplateFilters.js
function getTemplateFilters (line 33) | function getTemplateFilters(templates) {
FILE: packages/dashboard/src/components/cardGallery/index.js
function getPosterAltCopy (line 45) | function getPosterAltCopy(pageNumber) {
function CardGallery (line 53) | function CardGallery({ galleryPosters, isRTL, galleryLabel }) {
FILE: packages/dashboard/src/components/colorList/index.js
function ColorList (line 59) | function ColorList({ colors, size, spacing, ...rest }) {
FILE: packages/dashboard/src/components/fileUpload/index.js
function disableDefaults (line 96) | function disableDefaults(e) {
FILE: packages/dashboard/src/components/navProvider.js
function useNavContext (line 32) | function useNavContext(selector = identity) {
function NavProvider (line 36) | function NavProvider({ children }) {
FILE: packages/dashboard/src/components/pageStructure/leftRail.js
function LeftRail (line 59) | function LeftRail() {
FILE: packages/dashboard/src/components/pageStructure/menuButton.js
function NavMenuButton (line 60) | function NavMenuButton({ showOnlyOnSmallViewport }) {
FILE: packages/dashboard/src/components/popoverMenu/test/story-menu-generator.js
constant TEST_STORY (line 22) | const TEST_STORY = {
FILE: packages/dashboard/src/components/storyMenu/index.js
constant CONTEXT_MENU_BUTTON_CLASS (line 35) | const CONTEXT_MENU_BUTTON_CLASS = 'context-menu-button';
function StoryMenu (line 82) | function StoryMenu({
FILE: packages/dashboard/src/components/table/index.js
constant CELL_PADDING (line 28) | const CELL_PADDING = 16;
FILE: packages/dashboard/src/components/tooltip/tooltip.js
function Tooltip (line 32) | function Tooltip({ placement = Placement.Bottom, ...props }) {
FILE: packages/dashboard/src/components/viewStyleBar/index.js
function ViewStyleBar (line 56) | function ViewStyleBar({ onPress, layoutStyle }) {
FILE: packages/dashboard/src/constants/components.ts
constant DROPDOWN_TYPES (line 24) | const DROPDOWN_TYPES = {
constant DEFAULT_FILE_UPLOAD_TYPES (line 30) | const DEFAULT_FILE_UPLOAD_TYPES = ['.jpg', '.jpeg', '.png', '.gif'];
FILE: packages/dashboard/src/constants/index.ts
constant KEYBOARD_USER_CLASS (line 28) | const KEYBOARD_USER_CLASS = `useskeyboard`;
constant Z_INDEX (line 30) | const Z_INDEX = {
constant APP_ROUTES (line 38) | const APP_ROUTES = {
constant ROUTE_TITLES (line 44) | const ROUTE_TITLES = {
constant PRIMARY_PATHS (line 54) | const PRIMARY_PATHS = [
constant VIEW_STYLE (line 67) | const VIEW_STYLE = {
constant VIEW_STYLE_LABELS (line 72) | const VIEW_STYLE_LABELS = {
constant DASHBOARD_VIEWS (line 77) | const DASHBOARD_VIEWS = {
constant RESULT_LABELS (line 81) | const RESULT_LABELS = {
constant STORIES_PER_REQUEST (line 87) | const STORIES_PER_REQUEST = 24;
constant TEXT_INPUT_DEBOUNCE (line 89) | const TEXT_INPUT_DEBOUNCE = 300;
constant MIN_IMG_HEIGHT (line 91) | const MIN_IMG_HEIGHT = 96;
constant MIN_IMG_WIDTH (line 92) | const MIN_IMG_WIDTH = 96;
constant DEFAULT_GRID_IMG_HEIGHT (line 94) | const DEFAULT_GRID_IMG_HEIGHT = 853;
constant DEFAULT_GRID_IMG_WIDTH (line 95) | const DEFAULT_GRID_IMG_WIDTH = 640;
FILE: packages/dashboard/src/constants/pageStructure.ts
constant DASHBOARD_LEFT_NAV_WIDTH (line 19) | const DASHBOARD_LEFT_NAV_WIDTH = 288;
constant MIN_DASHBOARD_WIDTH (line 21) | const MIN_DASHBOARD_WIDTH = 1098;
constant VIEWPORT_BREAKPOINT (line 23) | const VIEWPORT_BREAKPOINT = {
constant STORY_PREVIEW_WIDTH (line 29) | const STORY_PREVIEW_WIDTH = {
constant GRID_SPACING (line 35) | const GRID_SPACING = {
constant PAGE_WRAPPER (line 40) | const PAGE_WRAPPER = {
FILE: packages/dashboard/src/constants/stories.ts
constant STORY_CONTEXT_MENU_ACTIONS (line 27) | const STORY_CONTEXT_MENU_ACTIONS = {
constant STORY_CONTEXT_MENU_ITEMS (line 37) | const STORY_CONTEXT_MENU_ITEMS = [
constant SORT_DIRECTION (line 76) | const SORT_DIRECTION = {
constant STORY_SORT_OPTIONS (line 81) | const STORY_SORT_OPTIONS = {
constant STORY_SORT_KEYS (line 88) | const STORY_SORT_KEYS = {
constant ORDER_BY_SORT (line 93) | const ORDER_BY_SORT = {
constant STORY_SORT_MENU_ITEMS (line 100) | const STORY_SORT_MENU_ITEMS = [
constant BASE_STATUSES (line 122) | const BASE_STATUSES = {
constant STORY_STATUS (line 130) | const STORY_STATUS = {
constant DISPLAY_STATUS (line 136) | const DISPLAY_STATUS = {
constant STORY_STATUSES (line 144) | const STORY_STATUSES = [
constant STORY_VIEWING_LABELS (line 177) | const STORY_VIEWING_LABELS = {
constant STORY_ANIMATION_STATE (line 246) | const STORY_ANIMATION_STATE = {
constant DEFAULT_FILTERS (line 253) | const DEFAULT_FILTERS = {
FILE: packages/dashboard/src/constants/templates.ts
constant TEMPLATE_CATEGORIES (line 22) | const TEMPLATE_CATEGORIES = {
constant TEMPLATE_CATEGORY_ITEMS (line 33) | const TEMPLATE_CATEGORY_ITEMS = [
constant TEMPLATE_COLORS (line 68) | const TEMPLATE_COLORS = {
constant TEMPLATE_COLOR_ITEMS (line 82) | const TEMPLATE_COLOR_ITEMS = [
constant TEMPLATES_GALLERY_STATUS (line 140) | const TEMPLATES_GALLERY_STATUS = {
constant TEMPLATES_GALLERY_VIEWING_LABELS (line 144) | const TEMPLATES_GALLERY_VIEWING_LABELS = {
constant TEMPLATE_SORT_DIRECTION (line 158) | const TEMPLATE_SORT_DIRECTION = {
constant TEMPLATES_GALLERY_SORT_OPTIONS (line 163) | const TEMPLATES_GALLERY_SORT_OPTIONS = {
constant TEMPLATE_SORT_KEYS (line 168) | const TEMPLATE_SORT_KEYS = {
constant DEFAULT_TEMPLATE_FILTERS (line 173) | const DEFAULT_TEMPLATE_FILTERS = {
constant TEMPLATES_GALLERY_SORT_MENU_ITEMS (line 182) | const TEMPLATES_GALLERY_SORT_MENU_ITEMS = [
constant TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS (line 193) | const TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS = {
FILE: packages/dashboard/src/dashboard.js
function Dashboard (line 45) | function Dashboard({ config, children }) {
FILE: packages/dashboard/src/karma/apiProviderFixture.js
function ApiProviderFixture (line 38) | function ApiProviderFixture({ children }) {
function getStoriesState (line 129) | function getStoriesState() {
function fetchStories (line 146) | function fetchStories({ sort = {}, filters = {} }, currentState) {
function updateStory (line 207) | function updateStory(story, currentState) {
function duplicateStory (line 222) | function duplicateStory(story, currentState) {
function trashStory (line 255) | function trashStory(story, currentState) {
function getTotalStoriesByStatus (line 271) | function getTotalStoriesByStatus(stories = []) {
function getTemplatesState (line 292) | function getTemplatesState() {
function fetchExternalTemplates (line 310) | function fetchExternalTemplates(currentState) {
function fetchExternalTemplateById (line 314) | function fetchExternalTemplateById(id, currentState) {
FILE: packages/dashboard/src/karma/fixture.js
constant FIXTURE_DEFAULT_CONFIG (line 58) | const FIXTURE_DEFAULT_CONFIG = {
class Fixture (line 88) | class Fixture {
method constructor (line 89) | constructor({ config = {}, flags = {} } = {}) {
method container (line 123) | get container() {
method events (line 134) | get events() {
method screen (line 138) | get screen() {
method setFlags (line 157) | setFlags(flags) {
method setConfig (line 162) | setConfig(config) {
method stubComponent (line 178) | stubComponent(component, matcher) {
method render (line 195) | async render() {
method restore (line 233) | restore() {
method renderHook (line 247) | renderHook(func) {
method act (line 262) | act(callback) {
method querySelector (line 272) | querySelector(selector) {
method querySelectorAll (line 282) | querySelectorAll(selector) {
method waitOnScreen (line 290) | waitOnScreen(element) {
method snapshot (line 313) | snapshot(name) {
FILE: packages/dashboard/src/storybookUtils/index.js
constant STORYBOOK_PAGE_SIZE (line 24) | const STORYBOOK_PAGE_SIZE = {
FILE: packages/dashboard/src/testUtils/mockApiProvider.js
function MockApiProvider (line 27) | function MockApiProvider({ children, value }) {
FILE: packages/dashboard/src/types/configProvider.ts
type Locale (line 23) | interface Locale {
type Capabilities (line 38) | interface Capabilities {
type Navigation (line 43) | interface Navigation {
type StyleConstants (line 50) | interface StyleConstants {
type QueryParams (line 55) | interface QueryParams {
type Author (line 62) | interface Author {
type Taxonomy (line 67) | type Taxonomy = {
type TaxonomiesArgs (line 82) | interface TaxonomiesArgs {
type TermArgs (line 87) | interface TermArgs {
type Term (line 92) | interface Term {
type ApiCallbacks (line 99) | interface ApiCallbacks {
type LockUser (line 113) | interface LockUser {
type DashboardStory (line 119) | interface DashboardStory {
type DashboardConfig (line 137) | interface DashboardConfig {
FILE: packages/dashboard/src/types/routerProvider.ts
type State (line 23) | interface State {
type Actions (line 30) | interface Actions {
type RouterProviderState (line 35) | interface RouterProviderState {
FILE: packages/dashboard/src/utils/keyboardOnlyOutline.js
constant ACCEPTED_KEYS (line 36) | const ACCEPTED_KEYS = [
FILE: packages/dashboard/src/utils/useDashboardResultsLabel.js
function useDashboardResultsLabel (line 28) | function useDashboardResultsLabel({
FILE: packages/dashboard/src/utils/usePagePreviewSize.js
function usePagePreviewSize (line 106) | function usePagePreviewSize(options = {}) {
FILE: packages/dashboard/src/utils/useStoryView.js
function useStoryView (line 43) | function useStoryView({
FILE: packages/dashboard/src/utils/useTemplateView.js
function useTemplateView (line 34) | function useTemplateView({
FILE: packages/date/src/constants.ts
constant FORMAT_TOKEN_SEPARATOR (line 17) | const FORMAT_TOKEN_SEPARATOR = '\u2006';
constant FORMAT_TOKEN_SEPARATOR_REGEX (line 19) | const FORMAT_TOKEN_SEPARATOR_REGEX = new RegExp(
FILE: packages/date/src/convertFormatString.ts
constant MINUTE_IN_SECONDS (line 29) | const MINUTE_IN_SECONDS = 60;
constant HOUR_IN_MINUTES (line 30) | const HOUR_IN_MINUTES = 60;
constant HOUR_IN_SECONDS (line 31) | const HOUR_IN_SECONDS = HOUR_IN_MINUTES * MINUTE_IN_SECONDS;
method S (line 56) | S(date: Date) {
method w (line 62) | w(date: Date) {
method z (line 67) | z(date: Date) {
method t (line 87) | t(date: Date) {
method L (line 92) | L(date: Date) {
method B (line 114) | B(date: Date) {
method I (line 155) | I() {
method Z (line 170) | Z(date: Date) {
method c (line 187) | c(date: Date) {
method r (line 196) | r(date: Date) {
type FormatMap (line 208) | type FormatMap = typeof formatMap;
type DateKey (line 209) | type DateKey = keyof FormatMap;
type ObtainKeys (line 210) | type ObtainKeys<Obj, Type> = {
type DateStringKey (line 213) | type DateStringKey = ObtainKeys<FormatMap, string>;
type DateFormatter (line 214) | type DateFormatter =
type DateFunctionKey (line 217) | type DateFunctionKey = ObtainKeys<FormatMap, DateFormatter>;
function convertFormatString (line 227) | function convertFormatString(dateFormat: string, date: Date) {
FILE: packages/date/src/format.ts
function format (line 36) | function format(date: Date | string, formatString: string) {
FILE: packages/date/src/formatDate.ts
function formatDate (line 29) | function formatDate(date: Date | string) {
FILE: packages/date/src/formatDistance.ts
type Token (line 22) | type Token = 'lessThanXMinutes' | 'xMinutes' | 'aboutXHours' | 'xHours';
type Formatter (line 23) | type Formatter = Record<Token, (count: number) => string>;
type Options (line 24) | type Options = {
method lessThanXMinutes (line 30) | lessThanXMinutes(count: number) {
method xMinutes (line 38) | xMinutes(count: number) {
method aboutXHours (line 46) | aboutXHours(count: number) {
method xHours (line 58) | xHours(count: number) {
function formatDistance (line 67) | function formatDistance(
FILE: packages/date/src/formatTime.ts
function formatTime (line 29) | function formatTime(date: Date | string) {
FILE: packages/date/src/getOptions.ts
function getOptions (line 47) | function getOptions() {
FILE: packages/date/src/getRelativeDisplayDate.ts
function getRelativeDisplayDate (line 40) | function getRelativeDisplayDate(date: Date | string) {
FILE: packages/date/src/getTimeZoneString.ts
function numberToUTCOffset (line 28) | function numberToUTCOffset(offset: number) {
function getTimeZoneString (line 54) | function getTimeZoneString() {
FILE: packages/date/src/hasLeadingZeros.ts
function hasLeadingZeros (line 22) | function hasLeadingZeros() {
FILE: packages/date/src/is12Hour.ts
function is12Hour (line 22) | function is12Hour() {
FILE: packages/date/src/settings.ts
type WeekdayIndex (line 17) | type WeekdayIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;
constant DEFAULT_DATE_SETTINGS (line 19) | const DEFAULT_DATE_SETTINGS = {
type Settings (line 28) | type Settings = {
function resetSettings (line 92) | function resetSettings() {
function updateSettings (line 101) | function updateSettings(newSettings: Partial<Settings>) {
function getSettings (line 113) | function getSettings() {
FILE: packages/date/src/test/getRelativeDisplayDate.ts
function getCurrentDate (line 36) | function getCurrentDate() {
FILE: packages/date/src/third_party/buildLocalizeFn.ts
type Era (line 15) | type Era = 0 | 1;
type Quarter (line 17) | type Quarter = 1 | 2 | 3 | 4;
type Day (line 19) | type Day = 0 | 1 | 2 | 3 | 4 | 5 | 6;
type Month (line 21) | type Month = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
type Unit (line 23) | type Unit =
type LocalePatternWidth (line 35) | type LocalePatternWidth = 'narrow' | 'short' | 'abbreviated' | 'wide' | ...
type LocaleDayPeriod (line 37) | type LocaleDayPeriod =
type LocaleUnit (line 47) | type LocaleUnit = Era | Quarter | Month | Day | LocaleDayPeriod;
type LocalizeUnitIndex (line 49) | type LocalizeUnitIndex<U extends LocaleUnit> = U extends LocaleUnit
type LocalizeFn (line 53) | type LocalizeFn<
type LocalizeEraValues (line 70) | type LocalizeEraValues = readonly [string, string];
type LocalizeQuarterValues (line 72) | type LocalizeQuarterValues = readonly [string, string, string, string];
type LocalizeDayValues (line 74) | type LocalizeDayValues = readonly [
type LocalizeMonthValues (line 84) | type LocalizeMonthValues = readonly [
type LocalizeUnitValuesIndex (line 99) | type LocalizeUnitValuesIndex<Values extends LocalizeUnitValues<any>> =
type LocalizeUnitValues (line 112) | type LocalizeUnitValues<U extends LocaleUnit> = U extends LocaleDayPeriod
type LocalizePeriodValuesMap (line 124) | type LocalizePeriodValuesMap<U extends LocaleUnit> = {
type BuildLocalizeFnArgCallback (line 128) | type BuildLocalizeFnArgCallback<Result extends LocaleUnit> = (
type BuildLocalizeFnArgs (line 132) | type BuildLocalizeFnArgs<
function buildLocalizeFn (line 144) | function buildLocalizeFn<
FILE: packages/date/src/toUTCDate.ts
function toUTCDate (line 31) | function toUTCDate(date: Date | string) {
FILE: packages/design-system/src/components/banner/banner.tsx
type BannerProps (line 88) | interface BannerProps {
FILE: packages/design-system/src/components/button/button.tsx
type WithTheme (line 40) | interface WithTheme {
type ElementProps (line 44) | interface ElementProps {
function getTextSize (line 229) | function getTextSize(size: ButtonSize): TextSize.Medium | TextSize.Small {
type Props (line 296) | type Props = PropsWithChildren<{
FILE: packages/design-system/src/components/button/constants.ts
type ButtonType (line 17) | enum ButtonType {
type ButtonSize (line 25) | enum ButtonSize {
type ButtonVariant (line 30) | enum ButtonVariant {
constant BUTTON_TRANSITION_TIMING (line 38) | const BUTTON_TRANSITION_TIMING = '0.3s ease 0s';
FILE: packages/design-system/src/components/button/stories/index.js
function ButtonContent (line 80) | function ButtonContent({ variant }) {
constant TOGGLE_VARIANTS (line 164) | const TOGGLE_VARIANTS = [ButtonVariant.Circle, ButtonVariant.Square];
FILE: packages/design-system/src/components/button/toggleButton.tsx
type ToggleProps (line 29) | interface ToggleProps extends Omit<
function ToggleButton (line 37) | function ToggleButton({ isToggled = false, type, ...rest }: ToggleProps) {
type LockProps (line 55) | interface LockProps extends ComponentPropsWithoutRef<'button'> {
function LockToggle (line 59) | function LockToggle({ isLocked = false, ...rest }: LockProps) {
FILE: packages/design-system/src/components/checkbox/checkbox.tsx
constant CONTAINER_WIDTH (line 31) | const CONTAINER_WIDTH = 24;
constant BORDER_WIDTH (line 32) | const BORDER_WIDTH = 1;
type CheckboxProps (line 94) | type CheckboxProps = ComponentPropsWithoutRef<'input'>;
FILE: packages/design-system/src/components/chip/chip.tsx
type ChipProps (line 107) | interface ChipProps extends ComponentPropsWithoutRef<'button'> {
FILE: packages/design-system/src/components/chip/stories/index.js
constant CHIP_STATES (line 42) | const CHIP_STATES = [
FILE: packages/design-system/src/components/circularProgress/circular.tsx
function CircularProgress (line 60) | function CircularProgress({
FILE: packages/design-system/src/components/contextMenu/animationContainer.tsx
constant PERCENTAGE_OFFSET (line 39) | const PERCENTAGE_OFFSET = {
type AnimationContainerProps (line 217) | interface AnimationContainerProps extends ComponentPropsWithoutRef<
function AnimationContainer (line 223) | function AnimationContainer({
FILE: packages/design-system/src/components/contextMenu/components/button.tsx
type MenuButtonProps (line 76) | interface MenuButtonProps extends ComponentPropsWithoutRef<
FILE: packages/design-system/src/components/contextMenu/components/group.tsx
type MenuGroupProps (line 22) | interface MenuGroupProps extends ComponentPropsWithoutRef<'div'> {
function Group (line 29) | function Group({ label, ...props }: MenuGroupProps) {
FILE: packages/design-system/src/components/contextMenu/components/icon.tsx
type MenuIconProps (line 40) | interface MenuIconProps extends ComponentPropsWithoutRef<'div'> {
function Icon (line 47) | function Icon({
FILE: packages/design-system/src/components/contextMenu/components/item.tsx
type MenuItemProps (line 55) | interface MenuItemProps extends ComponentPropsWithoutRef<
FILE: packages/design-system/src/components/contextMenu/components/link.tsx
type MenuLinkProps (line 57) | interface MenuLinkProps extends ComponentPropsWithoutRef<
function Link (line 71) | function Link({
FILE: packages/design-system/src/components/contextMenu/components/separator.tsx
function Separator (line 49) | function Separator() {
FILE: packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx
function getFocusableChildren (line 40) | function getFocusableChildren(parent: Element) {
type SubMenuTriggerProps (line 46) | interface SubMenuTriggerProps extends MenuItemProps {
function SubMenuTrigger (line 55) | function SubMenuTrigger({
FILE: packages/design-system/src/components/contextMenu/constants.ts
constant CONTEXT_MENU_SKIP_ELEMENT (line 28) | const CONTEXT_MENU_SKIP_ELEMENT = 'context-menu-skip-element';
constant CONTEXT_MENU_MIN_WIDTH (line 30) | const CONTEXT_MENU_MIN_WIDTH = 200;
FILE: packages/design-system/src/components/contextMenu/contextMenuProvider/provider.tsx
type ContextMenuProviderProps (line 27) | interface ContextMenuProviderProps {
function ContextMenuProvider (line 33) | function ContextMenuProvider({
FILE: packages/design-system/src/components/contextMenu/contextMenuProvider/useContextMenu.ts
function useContextMenu (line 30) | function useContextMenu<T>(
FILE: packages/design-system/src/components/contextMenu/menu.tsx
constant CONTEXT_MENU_MAX_WIDTH (line 45) | const CONTEXT_MENU_MAX_WIDTH = 300;
function getFocusableChildren (line 95) | function getFocusableChildren(parent: HTMLElement, isSubMenu?: boolean) {
FILE: packages/design-system/src/components/contextMenu/styled.tsx
constant POPOVER_Z_INDEX (line 25) | const POPOVER_Z_INDEX = 9991;
type SmartPopoverProps (line 54) | interface SmartPopoverProps extends ComponentPropsWithoutRef<
function SmartPopover (line 60) | function SmartPopover({ isRTL, ...props }: SmartPopoverProps) {
FILE: packages/design-system/src/components/contextMenu/types.ts
type InnerContextMenuProps (line 22) | interface InnerContextMenuProps {
type ContextMenuProps (line 35) | interface ContextMenuProps extends InnerContextMenuProps {
type ContextMenuState (line 48) | interface ContextMenuState {
type ContextMenuActions (line 54) | interface ContextMenuActions {
type ContextMenuProvider (line 61) | interface ContextMenuProvider {
FILE: packages/design-system/src/components/datalist/container.tsx
function OptionsContainerWithRef (line 77) | function OptionsContainerWithRef<O extends AbstractOption>(
FILE: packages/design-system/src/components/datalist/datalist.tsx
constant DEFAULT_WIDTH (line 50) | const DEFAULT_WIDTH = 240;
FILE: packages/design-system/src/components/datalist/list/defaultRenderer.tsx
function DefaultRendererWithRef (line 30) | function DefaultRendererWithRef<O extends AbstractOption>(
FILE: packages/design-system/src/components/datalist/list/list.tsx
function OptionListWithRef (line 59) | function OptionListWithRef<O extends AbstractOption>(
FILE: packages/design-system/src/components/datalist/searchInput.tsx
constant MAX_INPUT_SIZE (line 115) | const MAX_INPUT_SIZE = 35;
FILE: packages/design-system/src/components/datalist/types.ts
type AbstractOption (line 32) | interface AbstractOption {
type Group (line 37) | interface Group<O extends AbstractOption> {
type OptionRendererProps (line 43) | type OptionRendererProps<O extends AbstractOption> =
type OptionRenderer (line 50) | type OptionRenderer<O extends AbstractOption> = FunctionComponent<
type OptionListProps (line 54) | interface OptionListProps<O extends AbstractOption> {
type ContentRenderer (line 74) | type ContentRenderer<O> = (options: {
type OptionsContainerProps (line 82) | interface OptionsContainerProps<O> {
type SearchInputProps (line 95) | interface SearchInputProps extends Omit<
type DataListPropsOptions (line 107) | type DataListPropsOptions<O> =
type DataListProps (line 111) | type DataListProps<O extends AbstractOption> =
FILE: packages/design-system/src/components/dialog/dialog.tsx
type ModalProps (line 76) | type ModalProps = ComponentProps<typeof Modal>;
type DialogProps (line 77) | interface DialogProps extends ModalProps {
function Dialog (line 88) | function Dialog({
FILE: packages/design-system/src/components/disclosure/disclosure.tsx
type Direction (line 27) | type Direction = 'up' | 'down' | 'left' | 'right';
FILE: packages/design-system/src/components/dropDown/select/select.tsx
type DropDownSelectProps (line 30) | interface DropDownSelectProps extends ComponentPropsWithoutRef<'button'> {
FILE: packages/design-system/src/components/dropDown/types.ts
type UseDropDownProps (line 28) | interface UseDropDownProps {
type DropDownProps (line 33) | type DropDownProps = Omit<
FILE: packages/design-system/src/components/dropDown/useDropDown.ts
function useDropDown (line 34) | function useDropDown({
FILE: packages/design-system/src/components/hex/hex.tsx
type HexProps (line 42) | interface HexProps extends Omit<
FILE: packages/design-system/src/components/infiniteScroller/infiniteScroller.tsx
type State (line 56) | enum State {
type Action (line 63) | enum Action {
type InfiniteScrollProps (line 93) | interface InfiniteScrollProps {
function InfiniteScroller (line 103) | function InfiniteScroller({
FILE: packages/design-system/src/components/input/types.ts
type InputValue (line 22) | type InputValue = string | number;
type ParseInputProps (line 23) | interface ParseInputProps {
type AbstractNumericInputProps (line 30) | interface AbstractNumericInputProps extends ParseInputProps {
type UseNumericInputProps (line 37) | interface UseNumericInputProps extends AbstractNumericInputProps {
type InputProps (line 41) | interface InputProps extends ComponentPropsWithoutRef<'input'> {
type NumericInputProps (line 54) | type NumericInputProps = InputProps & AbstractNumericInputProps;
FILE: packages/design-system/src/components/input/validation.ts
function parseInput (line 22) | function parseInput(
function isInputValid (line 46) | function isInputValid(
FILE: packages/design-system/src/components/keyboard/gridview/useGridViewKeys.ts
type UseGridViewKeysProps (line 36) | interface UseGridViewKeysProps {
function useGridViewKeys (line 49) | function useGridViewKeys({
FILE: packages/design-system/src/components/keyboard/gridview/utils.ts
function focusOnPage (line 19) | function focusOnPage(page: Element | undefined) {
function getArrowDir (line 30) | function getArrowDir(
function getGridColumnAndRowCount (line 46) | function getGridColumnAndRowCount(grid: HTMLElement, pageCount: number) {
function getRow (line 64) | function getRow(index: number, numColumns: number) {
function getColumn (line 69) | function getColumn(index: number, numColumns: number) {
function getIndex (line 74) | function getIndex({
FILE: packages/design-system/src/components/keyboard/keyboard.tsx
function setGlobalRef (line 50) | function setGlobalRef() {
function useKeyEffectInternal (line 59) | function useKeyEffectInternal(
function useKeyEffect (line 112) | function useKeyEffect(
function useKeyDownEffect (line 122) | function useKeyDownEffect(
function useKeyUpEffect (line 132) | function useKeyUpEffect(
function useIsKeyPressed (line 142) | function useIsKeyPressed(
function useGlobalKeyDownEffect (line 166) | function useGlobalKeyDownEffect(
function useGlobalKeyUpEffect (line 175) | function useGlobalKeyUpEffect(
function useGlobalIsKeyPressed (line 185) | function useGlobalIsKeyPressed(
function useEscapeToBlurEffect (line 193) | function useEscapeToBlurEffect(
type ShortcutProps (line 212) | interface ShortcutProps {
function Shortcut (line 219) | function Shortcut({
FILE: packages/design-system/src/components/keyboard/test/index.js
function testIsKeyPressed (line 47) | function testIsKeyPressed(result, node, { key, which }, shouldRegister =...
FILE: packages/design-system/src/components/keyboard/utils.ts
constant PROP (line 34) | const PROP = '__WEB_STORIES_MT__';
constant NON_EDITABLE_INPUT_TYPES (line 35) | const NON_EDITABLE_INPUT_TYPES = [
constant CLICKABLE_INPUT_TYPES (line 46) | const CLICKABLE_INPUT_TYPES = [
type HTMLElementWithMouseTrap (line 56) | interface HTMLElementWithMouseTrap extends HTMLElement {
function getOrCreateMousetrap (line 64) | function getOrCreateMousetrap(node: HTMLElementWithMouseTrap) {
function getNodeFromRefOrNode (line 68) | function getNodeFromRefOrNode(refOrNode: RefOrNode) {
function resolveKeySpec (line 72) | function resolveKeySpec(keyDict: Keys, keyNameOrSpec: KeyNameOrSpec) {
function addMods (line 101) | function addMods(keys: string[], shift: boolean) {
type KeyHandlerProps (line 108) | interface KeyHandlerProps {
function createKeyHandler (line 116) | function createKeyHandler(
type ClickableHTMLElement (line 151) | type ClickableHTMLElement =
function isClickableTarget (line 156) | function isClickableTarget({ tagName, type }: ClickableHTMLElement) {
function isEditableTarget (line 166) | function isEditableTarget({
function crossesDialogBoundary (line 184) | function crossesDialogBoundary(target: Element, keyTarget: Element) {
function isPlatformMacOS (line 199) | function isPlatformMacOS() {
function getKeyForOS (line 207) | function getKeyForOS(key: string) {
function createShortcutAriaLabel (line 230) | function createShortcutAriaLabel(shortcut: string) {
function prettifyShortcut (line 281) | function prettifyShortcut(shortcut: string) {
FILE: packages/design-system/src/components/loadingBar/loadingBar.tsx
constant LOADING_INDICATOR_CLASS (line 30) | const LOADING_INDICATOR_CLASS = 'loading-indicator';
type LoadingBarProps (line 66) | interface LoadingBarProps extends ComponentPropsWithoutRef<'div'> {
function LoadingBar (line 70) | function LoadingBar({ loadingMessage, ...rest }: LoadingBarProps) {
FILE: packages/design-system/src/components/loadingSpinner/loadingSpinner.tsx
constant ANIMATION_DURATION (line 31) | const ANIMATION_DURATION = 0.85;
constant TAU (line 32) | const TAU = Math.PI * 2;
type LoadingSpinnerProps (line 94) | interface LoadingSpinnerProps extends ComponentPropsWithoutRef<'div'> {
function LoadingSpinner (line 101) | function LoadingSpinner({
FILE: packages/design-system/src/components/mediaInput/mediaInput.tsx
type MediaInputProps (line 166) | interface MediaInputProps extends Omit<
FILE: packages/design-system/src/components/mediaInput/types.ts
type MediaVariant (line 17) | enum MediaVariant {
FILE: packages/design-system/src/components/menu/constants.ts
constant DEFAULT_DROPDOWN_HEIGHT (line 17) | const DEFAULT_DROPDOWN_HEIGHT = 208;
constant KEYS_SHIFT_FOCUS (line 19) | const KEYS_SHIFT_FOCUS = ['up', 'down', 'left', 'right'];
constant KEYS_CLOSE_MENU (line 20) | const KEYS_CLOSE_MENU = ['esc', 'tab'];
constant KEYS_SELECT_ITEM (line 21) | const KEYS_SELECT_ITEM = ['space', 'enter'];
FILE: packages/design-system/src/components/menu/list/groupLabel.tsx
function GroupLabel (line 23) | function GroupLabel({ label }: { label?: string }) {
FILE: packages/design-system/src/components/menu/list/list.tsx
type ListProps (line 28) | interface ListProps {
FILE: packages/design-system/src/components/menu/list/listGroup.tsx
function ListGroup (line 30) | function ListGroup({
FILE: packages/design-system/src/components/menu/menu.tsx
function Menu (line 30) | function Menu({
FILE: packages/design-system/src/components/menu/stories/index.js
constant STANDARD_WIDTH (line 52) | const STANDARD_WIDTH = 400;
constant NARROW_WIDTH (line 53) | const NARROW_WIDTH = 150;
FILE: packages/design-system/src/components/menu/types.ts
type DropdownValue (line 32) | type DropdownValue = string | number | boolean;
type DropdownItem (line 33) | interface DropdownItem {
type NestedDropdownItem (line 38) | interface NestedDropdownItem {
type DefaultListItemProps (line 43) | interface DefaultListItemProps extends ComponentPropsWithoutRef<'li'> {
type ListItemProps (line 48) | type ListItemProps = DefaultListItemProps & RefAttributes<HTMLLIElement>;
type SharedMenuProps (line 50) | interface SharedMenuProps {
type UseDropDownMenuProps (line 64) | interface UseDropDownMenuProps extends Omit<
type ListGroupProps (line 71) | interface ListGroupProps extends Omit<
type MenuProps (line 79) | interface MenuProps extends SharedMenuProps {
FILE: packages/design-system/src/components/menu/useDropDownMenu.ts
function useDropDownMenu (line 39) | function useDropDownMenu({
FILE: packages/design-system/src/components/menu/utils.ts
function isValid (line 22) | function isValid(opt: DropdownItem) {
function getGroups (line 26) | function getGroups(
function getInset (line 50) | function getInset(
FILE: packages/design-system/src/components/modal/constants.ts
constant BODY_CLASS (line 17) | const BODY_CLASS = 'WebStories_ReactModal__Body--open';
constant CONTENT_CLASS (line 18) | const CONTENT_CLASS = 'WebStories_ReactModal__Content';
constant OVERLAY_CLASS (line 19) | const OVERLAY_CLASS = 'WebStories_ReactModal__Overlay';
FILE: packages/design-system/src/components/modal/modal.tsx
type ReactModalProps (line 54) | type ReactModalProps = ComponentProps<typeof ReactModal>;
type ModalProps (line 56) | interface ModalProps extends ReactModalProps {
function Modal (line 63) | function Modal({
FILE: packages/design-system/src/components/notificationBubble/notificationBubble.tsx
constant BUBBLE_DIAMETER (line 27) | const BUBBLE_DIAMETER = 24;
constant SMALL_BUBBLE_DIAMETER (line 28) | const SMALL_BUBBLE_DIAMETER = 20;
function getBubbleWidth (line 30) | function getBubbleWidth(numDigits: number) {
function NotificationBubble (line 72) | function NotificationBubble({
FILE: packages/design-system/src/components/notificationBubble/stories/index.js
constant VARIANT_OPTIONS (line 44) | const VARIANT_OPTIONS = Object.values(BubbleVariant);
FILE: packages/design-system/src/components/notificationBubble/types.ts
type BubbleVariant (line 21) | enum BubbleVariant {
type NotificationBubbleProps (line 31) | interface NotificationBubbleProps extends ComponentPropsWithoutRef<'div'> {
FILE: packages/design-system/src/components/pill/pill.tsx
type PillProps (line 70) | interface PillProps extends ComponentPropsWithoutRef<'button'> {
FILE: packages/design-system/src/components/pill/pillGroup.tsx
type PillOption (line 36) | interface PillOption {
type PillGroupProps (line 41) | interface PillGroupProps extends Omit<
function PillGroup (line 50) | function PillGroup({ options, value, onSelect, ...rest }: PillGroupProps) {
FILE: packages/design-system/src/components/pill/stories/index.js
function PillContainer (line 58) | function PillContainer({ prefix, onClick, ...args }) {
constant PILL_OPTIONS (line 115) | const PILL_OPTIONS = [
function PillGroupContainer (line 122) | function PillGroupContainer(args) {
FILE: packages/design-system/src/components/popup/constants.ts
type Placement (line 22) | enum Placement {
constant RTL_PLACEMENT (line 37) | const RTL_PLACEMENT = {
FILE: packages/design-system/src/components/popup/popup.tsx
constant DEFAULT_TOP_OFFSET (line 41) | const DEFAULT_TOP_OFFSET = 0;
constant DEFAULT_POPUP_Z_INDEX (line 42) | const DEFAULT_POPUP_Z_INDEX = 2;
constant DEFAULT_LEFT_OFFSET (line 43) | const DEFAULT_LEFT_OFFSET = 0;
type PopupProps (line 45) | interface PopupProps {
function Popup (line 60) | function Popup({
FILE: packages/design-system/src/components/popup/types.ts
type Spacing (line 17) | interface Spacing {
type Rectangle (line 22) | interface Rectangle {
type Offset (line 29) | interface Offset extends Spacing {
FILE: packages/design-system/src/components/popup/utils/getOffset.ts
function getXOffset (line 29) | function getXOffset(
function getYOffset (line 64) | function getYOffset(
constant EMPTY_OFFSET (line 90) | const EMPTY_OFFSET = {
type GetOffsetProps (line 98) | interface GetOffsetProps {
function getOffset (line 110) | function getOffset({
FILE: packages/design-system/src/components/popup/utils/getTransforms.ts
function getXTransforms (line 22) | function getXTransforms(placement: Placement, isRTL: boolean) {
function getYTransforms (line 38) | function getYTransforms(placement: Placement) {
function getTransforms (line 54) | function getTransforms(placement: Placement, isRTL: boolean) {
FILE: packages/design-system/src/components/radio/radio.tsx
constant BORDER_WIDTH (line 31) | const BORDER_WIDTH = 1;
constant TEXT_GAP_HEIGHT (line 32) | const TEXT_GAP_HEIGHT = 8;
constant RING_DIAMETER (line 33) | const RING_DIAMETER = 24;
constant CONTAINER_HEIGHT (line 34) | const CONTAINER_HEIGHT = 44;
constant RADIO_DIAMETER (line 35) | const RADIO_DIAMETER = 16;
type RadioProps (line 134) | interface RadioProps extends Omit<ComponentPropsWithoutRef<'input'>, 'ty...
FILE: packages/design-system/src/components/search/constants.ts
constant DEFAULT_POPUP_FILL_WIDTH (line 22) | const DEFAULT_POPUP_FILL_WIDTH = 276;
constant DEFAULT_PLACEHOLDER (line 23) | const DEFAULT_PLACEHOLDER = __('Search', 'web-stories');
constant DEFAULT_ARIA_CLEAR_LABEL (line 24) | const DEFAULT_ARIA_CLEAR_LABEL = __('Clear Search', 'web-stories');
constant DEFAULT_ARIA_INPUT_LABEL (line 25) | const DEFAULT_ARIA_INPUT_LABEL = __('Search', 'web-stories');
constant Z_INDEX (line 27) | const Z_INDEX = {
FILE: packages/design-system/src/components/search/input/input.tsx
type SearchInputProps (line 42) | interface SearchInputProps extends ComponentPropsWithoutRef<typeof Input> {
FILE: packages/design-system/src/components/search/search.tsx
function Search (line 51) | function Search({
FILE: packages/design-system/src/components/search/types.ts
type UseSearchProps (line 23) | interface UseSearchProps {
type SearchProps (line 30) | interface SearchProps extends Omit<UseSearchProps, 'options'> {
FILE: packages/design-system/src/components/search/useSearch.ts
function useSearch (line 36) | function useSearch({
FILE: packages/design-system/src/components/slider/slider.tsx
type SliderElementProps (line 37) | interface SliderElementProps {
constant DEFAULT_SIZE (line 43) | const DEFAULT_SIZE = 24;
function getAdjustedWidthValue (line 149) | function getAdjustedWidthValue(value = 0, thumbSize: number, width: numb...
function getFocusedThumbMargin (line 157) | function getFocusedThumbMargin(
type SliderProps (line 184) | interface SliderProps extends ComponentProps<typeof Input> {
function Slider (line 207) | function Slider({
FILE: packages/design-system/src/components/snackbar/snackbarContainer.tsx
function getSnackbarXPos (line 58) | function getSnackbarXPos({ placement }: { placement: SnackbarPlacement }) {
type SnackbarContainerProps (line 98) | interface SnackbarContainerProps {
function SnackbarContainer (line 108) | function SnackbarContainer({
FILE: packages/design-system/src/components/snackbar/snackbarMessage.tsx
type SnackbarMessageProps (line 179) | interface SnackbarMessageProps extends ComponentPropsWithoutRef<'div'> {
function SnackbarMessage (line 193) | function SnackbarMessage({
FILE: packages/design-system/src/components/snackbar/test/snackbarContainer.js
constant NOTIFICATIONS (line 28) | const NOTIFICATIONS = [
constant NOTIFICATION_WITH_ACTION_AND_HELP_TEXT (line 46) | const NOTIFICATION_WITH_ACTION_AND_HELP_TEXT = {
FILE: packages/design-system/src/components/snackbar/types.ts
constant AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX (line 17) | const AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX = 10000;
constant AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MIN (line 18) | const AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MIN = 1200;
constant DEFAULT_MESSAGE_Z_INDEX (line 19) | const DEFAULT_MESSAGE_Z_INDEX = 15;
type SnackbarPlacement (line 21) | enum SnackbarPlacement {
type ThumbnailStatus (line 30) | enum ThumbnailStatus {
type SnackbarNotificationThumbnail (line 35) | interface SnackbarNotificationThumbnail {
type SnackbarNotification (line 41) | interface SnackbarNotification {
FILE: packages/design-system/src/components/swatch/stories/index.js
constant DEMO_COLORS (line 64) | const DEMO_COLORS = [
constant VARIANTS (line 146) | const VARIANTS = [
function _default (line 165) | function _default(args) {
FILE: packages/design-system/src/components/swatch/swatch.tsx
constant SIZE (line 35) | const SIZE = 24;
type SwatchProps (line 123) | interface SwatchProps extends Omit<ComponentPropsWithoutRef<'button'>, '...
function Swatch (line 130) | function Swatch({
FILE: packages/design-system/src/components/switch/switch.tsx
constant SWITCH_HEIGHT (line 34) | const SWITCH_HEIGHT = 32;
type Value (line 35) | enum Value {
type SwitchProps (line 149) | interface SwitchProps extends Omit<
FILE: packages/design-system/src/components/textArea/textArea.tsx
type TextAreaProps (line 131) | interface TextAreaProps extends Omit<
FILE: packages/design-system/src/components/toggle/toggle.tsx
constant BORDER_WIDTH (line 27) | const BORDER_WIDTH = 1;
constant TOGGLE_TRACK_HEIGHT (line 28) | const TOGGLE_TRACK_HEIGHT = 20;
constant TOGGLE_WIDTH (line 29) | const TOGGLE_WIDTH = 44;
constant CIRCLE_DIAMETER (line 30) | const CIRCLE_DIAMETER = 28;
constant WRAPPER_PADDING (line 31) | const WRAPPER_PADDING = (CIRCLE_DIAMETER - TOGGLE_TRACK_HEIGHT) / 2;
constant CIRCLE_INITIAL_POSITION (line 32) | const CIRCLE_INITIAL_POSITION =
constant CIRCLE_FINAL_POSITION (line 34) | const CIRCLE_FINAL_POSITION =
constant ICON_CONTAINER_WIDTH (line 37) | const ICON_CONTAINER_WIDTH = 32;
constant ICON_TOP_POSITION (line 38) | const ICON_TOP_POSITION = -6;
constant ICON_LEFT_POSITION (line 39) | const ICON_LEFT_POSITION = 19;
type ToggleProps (line 188) | type ToggleProps = ComponentPropsWithoutRef<'input'>;
function Toggle (line 190) | function Toggle({ className, ...inputProps }: ToggleProps) {
FILE: packages/design-system/src/components/tooltip/tail.tsx
constant SVG_TOOLTIP_TAIL_ID (line 27) | const SVG_TOOLTIP_TAIL_ID = 'tooltip-tail';
constant TAIL_WIDTH (line 28) | const TAIL_WIDTH = 34;
constant TAIL_HEIGHT (line 29) | const TAIL_HEIGHT = 8;
type TailPositionProps (line 31) | interface TailPositionProps {
FILE: packages/design-system/src/components/tooltip/tooltip.tsx
constant SPACE_BETWEEN_TOOLTIP_AND_ELEMENT (line 53) | const SPACE_BETWEEN_TOOLTIP_AND_ELEMENT = TAIL_HEIGHT;
constant DELAY_MS (line 55) | const DELAY_MS = 1000;
constant REPEAT_DELAYED_MS (line 57) | const REPEAT_DELAYED_MS = 500;
constant DEFAULT_LEFT_OFFSET (line 59) | const DEFAULT_LEFT_OFFSET = 0;
constant DEFAULT_POPUP_Z_INDEX (line 61) | const DEFAULT_POPUP_Z_INDEX = 2;
type TooltipProps (line 100) | interface TooltipProps extends ComponentPropsWithoutRef<'div'> {
function Tooltip (line 111) | function Tooltip({
FILE: packages/design-system/src/components/typography/link/index.tsx
type LinkTextSize (line 43) | type LinkTextSize =
function ConditionalSpanWrapper (line 75) | function ConditionalSpanWrapper({
type LinkProps (line 83) | interface LinkProps extends ComponentPropsWithoutRef<'a'> {
FILE: packages/design-system/src/components/typography/list/index.ts
type ListTextSize (line 28) | type ListTextSize =
FILE: packages/design-system/src/components/typography/text/index.ts
type TextProps (line 28) | interface TextProps {
type TextPropsWithTheme (line 34) | interface TextPropsWithTheme extends TextProps {
FILE: packages/design-system/src/contexts/popup/types.ts
type PopupState (line 17) | interface PopupState {
FILE: packages/design-system/src/contexts/popup/usePopup.ts
function usePopup (line 30) | function usePopup<T>(
FILE: packages/design-system/src/contexts/snackbar/snackbarProvider.tsx
type SnackbarProviderProps (line 30) | interface SnackbarProviderProps {
function SnackbarProvider (line 34) | function SnackbarProvider({
FILE: packages/design-system/src/contexts/snackbar/useSnackbar.ts
function useSnackbar (line 30) | function useSnackbar<T>(
FILE: packages/design-system/src/icons/stories/index.js
function IconDisplay (line 64) | function IconDisplay({ getStyle = () => {} }) {
FILE: packages/design-system/src/theme/constants/breakpoints.ts
constant BREAKPOINTS (line 16) | const BREAKPOINTS = {
FILE: packages/design-system/src/theme/constants/index.ts
constant ICON_SIZE (line 22) | const ICON_SIZE = 32;
constant LARGE_BUTTON_SIZE (line 23) | const LARGE_BUTTON_SIZE = 56;
constant SCROLLBAR_WIDTH (line 25) | const SCROLLBAR_WIDTH = 11;
constant THEME_CONSTANTS (line 27) | const THEME_CONSTANTS = {
constant BEZIER (line 34) | const BEZIER = {
FILE: packages/design-system/src/theme/helpers/expandPresetStyles.ts
type ExpandPresetStylesProps (line 29) | interface ExpandPresetStylesProps {
type PresetChoices (line 49) | type PresetChoices = Theme['typography']['presets'];
type PresetSelector (line 50) | type PresetSelector = (
FILE: packages/design-system/src/theme/theme.ts
type Theme (line 34) | type Theme = typeof theme;
FILE: packages/design-system/src/theme/types.ts
type TextSize (line 17) | enum TextSize {
type ParagraphSize (line 28) | type ParagraphSize =
type DisplaySize (line 35) | type DisplaySize = TextSize.Large | TextSize.Medium | TextSize.Small;
type HeadlineSize (line 37) | type HeadlineSize =
FILE: packages/design-system/src/types/keyboard.ts
type KeySpec (line 27) | interface KeySpec {
type Keys (line 36) | type Keys = typeof keys;
type KeyEffectCallback (line 37) | type KeyEffectCallback = (event: KeyboardEvent) => void;
type KeyNameOrSpec (line 38) | type KeyNameOrSpec = KeySpec | string | string[];
type RefOrNode (line 40) | type RefOrNode = Element | RefObj
Copy disabled (too large)
Download .json
Condensed preview — 4493 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (28,458K chars).
[
{
"path": ".allstar/branch_protection.yaml",
"chars": 596,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".browserslistrc",
"chars": 133,
"preview": "last 2 Chrome versions\nlast 2 Firefox versions\nlast 2 Safari versions\nlast 2 iOS versions\nlast 2 Edge versions\nlast 2 Op"
},
{
"path": ".distignore",
"chars": 1234,
"preview": ".allstar\n.git\n.github\n.husky\n.idea\n.rollup.cache\n.storybook\n.wordpress-org\n__mocks__\n__static__\nassets/testjs\nbin\nbuild\n"
},
{
"path": ".editorconfig",
"chars": 323,
"preview": "# WordPress Coding Standards\n# https://make.wordpress.org/core/handbook/coding-standards/\n\nroot = true\n\n[*]\ncharset = ut"
},
{
"path": ".eslintignore",
"chars": 168,
"preview": "**/node_modules/**\n**/vendor/**\n**/dist/**\n**/dist-module/**\n**/dist-types/**\n**/assets/js/*.js\n**/packages/migration/sc"
},
{
"path": ".eslintrc",
"chars": 28148,
"preview": "{\n \"root\": true,\n \"parser\": \"@babel/eslint-parser\",\n \"extends\": [\n \"plugin:@wordpress/eslint-plugin/i18n\",\n \"es"
},
{
"path": ".git-blame-ignore-revs",
"chars": 246,
"preview": "bf0cb0583153e71fcceaee044550ad511b94d470\n1e93c55d2c9e596404646a3bd1785f6249f9945c\nfe28ba3ced458b23fc53574bb25d6d3fbe6a4b"
},
{
"path": ".gitattributes",
"chars": 748,
"preview": "*.snap linguist-generated=true\n.github export-ignore\n.storybook export-ignore\n.wordpress-org export-ignore\n__mocks__ exp"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 832,
"preview": "---\nname: Bug Report\nabout: Create a report to help us improve.\ntitle: ''\nlabels: 'Type: Bug'\nassignees: ''\n---\n\n<!--\nNO"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 54,
"preview": "# todo: disable in future?\nblank_issues_enabled: true\n"
},
{
"path": ".github/ISSUE_TEMPLATE/enhancement.md",
"chars": 634,
"preview": "---\nname: Enhancement\nabout: Suggest an idea for this project.\ntitle: ''\nlabels: 'Type: Enhancement'\nassignees: ''\n---\n\n"
},
{
"path": ".github/ISSUE_TEMPLATE/epic.md",
"chars": 847,
"preview": "---\nname: Epic\nabout: A theme of work that contains several issues or sub-tasks.\ntitle: ''\nlabels: 'Epic'\nassignees: ''\n"
},
{
"path": ".github/ISSUE_TEMPLATE/task.md",
"chars": 372,
"preview": "---\nname: Task\nabout: Tasks which do not involve engineering.\ntitle: ''\nlabels: 'Type: Task'\nassignees: ''\n---\n\n<!-- NOT"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 2002,
"preview": "## Summary\n\n<!-- A brief description of what this PR does. -->\n\n## User-facing changes\n\n<!--\nPlease describe your change"
},
{
"path": ".github/SUPPORT.md",
"chars": 401,
"preview": "Thank you for being an early adopter of Web Stories for WordPress! We're working around the clock to improve your experi"
},
{
"path": ".github/dependabot.yml",
"chars": 2220,
"preview": "version: 2\nupdates:\n - package-ecosystem: github-actions\n directory: '/'\n schedule:\n interval: quarterly\n "
},
{
"path": ".github/release.yml",
"chars": 500,
"preview": "changelog:\n exclude:\n authors:\n - dependabot\n - github-actions\n - googleforcreators-bot\n categories:"
},
{
"path": ".github/workflows/build-and-deploy.yml",
"chars": 3519,
"preview": "name: Build plugin\n\non:\n push:\n # Don't run for irrelevant changes.\n paths-ignore:\n - 'docs/**'\n - '.st"
},
{
"path": ".github/workflows/codeql-analysis.yml",
"chars": 1254,
"preview": "name: CodeQL\n\non:\n push:\n # Only run if JS files changed.\n paths:\n - '**.js'\n - '**.cjs'\n - '**.ts"
},
{
"path": ".github/workflows/deploy-storybook.yml",
"chars": 2260,
"preview": "name: Deploy to GH Pages\n\non:\n push:\n # Don't run for irrelevant changes.\n paths-ignore:\n - 'docs/**'\n "
},
{
"path": ".github/workflows/lint-css-js-md.yml",
"chars": 4016,
"preview": "name: Lint CSS/JS/MD\n\non:\n push:\n # Only run if CSS/JS/MD-related files changed.\n paths:\n - '**.js'\n - "
},
{
"path": ".github/workflows/lint-i18n.yml",
"chars": 3866,
"preview": "name: Lint I18N\n\non:\n push:\n paths:\n - '**.js'\n - '**.cjs'\n - '**.ts'\n - '**.tsx'\n - '**/pa"
},
{
"path": ".github/workflows/lint-php.yml",
"chars": 2520,
"preview": "name: Lint PHP\n\non:\n push:\n # Only run if PHP-related files changed.\n paths:\n - '**.php'\n - 'phpcs.xml."
},
{
"path": ".github/workflows/lint-plugin-check.yml",
"chars": 2542,
"preview": "name: Plugin Check\n\non:\n push:\n paths:\n - '**.js'\n - '**.cjs'\n - '**.ts'\n - '**.tsx'\n - '**"
},
{
"path": ".github/workflows/npm-release.yml",
"chars": 6459,
"preview": "# npm packages release automation\n\nname: npm Release\n\non:\n workflow_dispatch:\n\npermissions:\n contents: read\n\n# Cancels"
},
{
"path": ".github/workflows/plugin-release.yml",
"chars": 21705,
"preview": "# Plugin release automation\n#\n# Builds the plugin for release candidates and stable releases.\n#\n# Creates the release br"
},
{
"path": ".github/workflows/scorecards.yml",
"chars": 1967,
"preview": "name: Scorecards supply-chain security\n\non:\n # Only the default branch is supported.\n branch_protection_rule:\n schedu"
},
{
"path": ".github/workflows/tests-e2e.yml",
"chars": 7203,
"preview": "name: E2E Tests\n\non:\n push:\n # Don't run for irrelevant changes.\n paths-ignore:\n - 'docs/**'\n - '.story"
},
{
"path": ".github/workflows/tests-karma-dashboard.yml",
"chars": 3557,
"preview": "name: Dashboard Integration Tests\n\non:\n push:\n # Only run if dashboard-related files changed.\n paths:\n - 'ba"
},
{
"path": ".github/workflows/tests-karma-editor.yml",
"chars": 4567,
"preview": "name: Editor Integration Tests\n\non:\n push:\n # Only run if editor-related files changed.\n paths:\n - 'babel.co"
},
{
"path": ".github/workflows/tests-unit-js.yml",
"chars": 3381,
"preview": "name: JavaScript Unit Tests\n\non:\n push:\n # Only run if JS-related files changed.\n paths:\n - '**.js'\n - "
},
{
"path": ".github/workflows/tests-unit-php.yml",
"chars": 6510,
"preview": "name: PHP Unit Tests\n\non:\n push:\n # Only run if PHP-related files changed.\n paths:\n - '**.php'\n - 'phpu"
},
{
"path": ".github/workflows/update-browserslist.yml",
"chars": 1579,
"preview": "name: Update browserslist db\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 12 1 * *'\n\npermissions:\n contents: re"
},
{
"path": ".github/workflows/update-google-fonts.yml",
"chars": 1919,
"preview": "name: Update Google Fonts\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 12 1 * *'\n\npermissions:\n contents: read\n"
},
{
"path": ".github/workflows/update-product-schema.yml",
"chars": 1797,
"preview": "name: Update Product Schema\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 12 1 * *'\n\npermissions:\n contents: rea"
},
{
"path": ".github/workflows/update-templates.yml",
"chars": 1730,
"preview": "name: Migrate Templates\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 12 * * 1'\n\nenv:\n GIT_AUTHOR_EMAIL: 9492372"
},
{
"path": ".gitignore",
"chars": 440,
"preview": ".rollup.cache\n.test_artifacts\n.idea/\n.vscode/\n.DS_Store\nnode_modules\n/assets\n/packages/migration/scripts/module.js\n/pack"
},
{
"path": ".husky/pre-commit",
"chars": 247,
"preview": "#!/bin/sh\n\n# TODO: Move to ~/.huskyrc instead.\n# See https://typicode.github.io/husky/#/?id=command-not-found\nexport NVM"
},
{
"path": ".markdownlint.json",
"chars": 192,
"preview": "{\n \"default\": true,\n \"MD003\": { \"style\": \"atx\" },\n \"MD007\": { \"indent\": 4 },\n \"MD013\": { \"line_length\": 9999 },\n \"n"
},
{
"path": ".markdownlintignore",
"chars": 61,
"preview": ".github\n__mocks__\nassets\nbin\nbuild\nnode_modules\ntests\nvendor\n"
},
{
"path": ".npmpackagejsonlintrc.json",
"chars": 3440,
"preview": "{\n \"rules\": {\n \"bin-type\": \"error\",\n \"bundledDependencies-type\": \"error\",\n \"config-type\": \"error\",\n \"cpu-ty"
},
{
"path": ".npmrc",
"chars": 38,
"preview": "save-exact = false\nlockfile-version=3\n"
},
{
"path": ".nvmrc",
"chars": 3,
"preview": "24\n"
},
{
"path": ".oxlintrc.json",
"chars": 2469,
"preview": "{\n\t\"$schema\": \"./node_modules/oxlint/configuration_schema.json\",\n\t\"categories\": {\n\t\t\"correctness\": \"error\",\n\t\t\"nursery\":"
},
{
"path": ".phpstorm.config.js",
"chars": 3640,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".phpstorm.meta.php",
"chars": 7096,
"preview": "<?php\n\nnamespace PHPSTORM_META {\n\n\toverride(\n\t\t\\Google\\Web_Stories\\Services::get(),\n\n\t\t// TODO: I'd like to use Plugin::"
},
{
"path": ".prettierignore",
"chars": 422,
"preview": "/.idea\n/bin/local-env/uploads.ini\n/bin/local-env/data\n/build\n/docs\n/node_modules\n/vendor\n/assets/css\n/assets/js\n/assets/"
},
{
"path": ".prettierrc",
"chars": 623,
"preview": "{\n \"plugins\": [\"@prettier/plugin-xml\"],\n \"printWidth\": 80,\n \"singleQuote\": true,\n \"trailingComma\": \"es5\",\n \"bracket"
},
{
"path": ".storybook/main.cjs",
"chars": 8142,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/manager-head.html",
"chars": 60,
"preview": "<style>\n\t#playground-preview {\n\t\tdisplay: none;\n\t}\n</style>\n"
},
{
"path": ".storybook/preview-head.html",
"chars": 920,
"preview": "<!--\n ~ Copyright 2020 Google LLC\n ~\n ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n ~ you may n"
},
{
"path": ".storybook/preview.js",
"chars": 4334,
"preview": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/dashboard/index.js",
"chars": 3526,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/dashboard/theme.js",
"chars": 887,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/api/fonts.js",
"chars": 1247,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/api/index.js",
"chars": 804,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/api/media.js",
"chars": 1175,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/api/story.js",
"chars": 1640,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/constants.js",
"chars": 742,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/getDummyMedia.js",
"chars": 11702,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/header/buttons/index.js",
"chars": 1780,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/header/buttons/preview.js",
"chars": 2535,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/header/buttons/saveButton.js",
"chars": 1503,
"preview": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/header/index.js",
"chars": 1381,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/index.js",
"chars": 1635,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".storybook/stories/playground/story-editor/preview.js",
"chars": 1247,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": ".stylelintignore",
"chars": 159,
"preview": ".github\n.storybook\n.wordpress-org\n__mocks__\n__static__\nassets\nbin\nblocks\nbuild\ndocs\nincludes\nnode_modules\npatches\npublic"
},
{
"path": ".stylelintrc",
"chars": 1103,
"preview": "{\n \"extends\": [\n \"stylelint-config-recommended\"\n ],\n \"plugins\": [\"stylelint-prettier\"],\n \"customSyntax\": \"postcss"
},
{
"path": ".wordpress-org/README.md",
"chars": 166,
"preview": "# WordPress.org assets\n\nThese assets are used in the WordPress.org plugin directory. They will need to be synced with th"
},
{
"path": ".wordpress-org/blueprints/blueprint.json",
"chars": 622,
"preview": "{\n \"$schema\": \"https://playground.wordpress.net/blueprint-schema.json\",\n \"landingPage\": \"/wp-admin/plugins.php\",\n \"pr"
},
{
"path": "CONTRIBUTING.md",
"chars": 1201,
"preview": "# How to Contribute\n\nWe'd love to accept your patches and contributions to this project. There are\njust a few small guid"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 3196,
"preview": "# Web Stories for WordPress\n\nVisual storytelling for WordPress.\n\n[;\n * you may not use"
},
{
"path": "__mocks__/node:fs.js",
"chars": 3079,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "__mocks__/react-moveable.js",
"chars": 813,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "__static__/README.md",
"chars": 69,
"preview": "# Static files\n\nThese are static files that can be used for testing.\n"
},
{
"path": "babel.config.cjs",
"chars": 2115,
"preview": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
},
{
"path": "bin/deploy-to-test-environment.sh",
"chars": 3111,
"preview": "#!/usr/bin/env bash\n\nset -e\n\n#\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "bin/install-wp-tests.sh",
"chars": 6389,
"preview": "#!/usr/bin/env bash\n\n#\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n#"
},
{
"path": "bin/local-env/docker-compose.yml",
"chars": 1712,
"preview": "services:\n wordpress:\n image: wordpress:php${PHP_VERSION:-8.2}\n ports:\n - '127.0.0.1:8899:80'\n environmen"
},
{
"path": "bin/local-env/includes.sh",
"chars": 4289,
"preview": "#!/usr/bin/env bash\n\n# Common variables.\nDOCKER_COMPOSE_FILE_OPTIONS=\"-f $(dirname \"$0\")/docker-compose.yml\"\n\nif [ -f \"$"
},
{
"path": "bin/local-env/install-wordpress.sh",
"chars": 10413,
"preview": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Common variables.\nWP_DEBUG=${WP_DEBUG-true}\nSCRIPT_DEBUG=${S"
},
{
"path": "bin/local-env/launch-containers.sh",
"chars": 931,
"preview": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Include useful functions.\n. \"$(dirname \"$0\")/includes.sh\"\n\n#"
},
{
"path": "bin/local-env/start.sh",
"chars": 1262,
"preview": "#!/usr/bin/env bash\n\n# Exit if any command fails\nset -e\n\n# Include useful functions\n. \"$(dirname \"$0\")/includes.sh\"\n\n# C"
},
{
"path": "bin/local-env/stop.sh",
"chars": 728,
"preview": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Include useful functions.\n. \"$(dirname \"$0\")/includes.sh\"\n\n#"
},
{
"path": "bin/local-env/uploads.ini",
"chars": 50,
"preview": "upload_max_filesize = 100M;\npost_max_size = 100M;\n"
},
{
"path": "bin/schemas/story.json",
"chars": 22255,
"preview": "{\n \"$id\": \"https://wp.stories.google/schema/story.json\",\n \"type\": \"object\",\n \"default\": {},\n \"title\": \"Web Stories f"
},
{
"path": "bin/setup-local-npm-registry.sh",
"chars": 1345,
"preview": "#!/usr/bin/env bash\n\n#\n# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n#"
},
{
"path": "bin/stop-local-npm-registry.sh",
"chars": 659,
"preview": "#!/usr/bin/env bash\n\n#\n# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n#"
},
{
"path": "bin/verdaccio-config.yml",
"chars": 1412,
"preview": "#\n# This is the default config file. It allows all users to do anything,\n# so don't use it on production systems.\n#\n# Lo"
},
{
"path": "blocks/embed/block.json",
"chars": 1776,
"preview": "{\n \"name\": \"web-stories/embed\",\n \"title\": \"Web Stories\",\n \"description\": \"Embed Web Stories.\",\n \"category\": \"embed\","
},
{
"path": "codecov.yml",
"chars": 2312,
"preview": "# Overall settings for PR integration via codecov.io\n# See https://docs.codecov.io/docs/codecovyml-reference\n\n# Separate"
},
{
"path": "composer.json",
"chars": 4337,
"preview": "{\n \"name\": \"googleforcreators/web-stories-wp\",\n \"description\": \"Visual storytelling for WordPress.\",\n \"license\": \"Apa"
},
{
"path": "docs/README.md",
"chars": 1810,
"preview": "# Technical Documentation\n\n## Introduction\n\n* [Getting Started](./getting-started.md)\n* [Glossary](./glossary.md)\n\n## Co"
},
{
"path": "docs/accessibility-guidelines.md",
"chars": 1541,
"preview": "# Accessibility Guidelines\n\nThis project follows web accessibility practices and patterns outlined by [WAI-ARIA](https:/"
},
{
"path": "docs/accessibility-testing.md",
"chars": 3407,
"preview": "# Accessibility Testing\n\n## Manual Testing\n\n### Resources\n\n* [Introduction to Keyboard Navigation](https://rianrietveld."
},
{
"path": "docs/animations.md",
"chars": 6227,
"preview": "# Animations\n\nAnimations currently reside in `packages/animation`. The top level logic is held in `packages/animation/sr"
},
{
"path": "docs/architecture.md",
"chars": 1684,
"preview": "# Architecture\n\n## Design Principles\n\nThe story editor’s architecture follows the following design principles (amongst o"
},
{
"path": "docs/browser-support.md",
"chars": 505,
"preview": "# Browser and device support\n\nWe support roughly the same set of browsers as the AMP Project to align with the AMP story"
},
{
"path": "docs/canvas.md",
"chars": 138,
"preview": "# Canvas\n\n## Layers\n\n site inste"
},
{
"path": "docs/checklist.md",
"chars": 2656,
"preview": "# Checklist \n\nThe Prepublish Checklist to help users make the best Stories possible.\n\n## Logic \n\n- On an empty story non"
},
{
"path": "docs/code-style.md",
"chars": 498,
"preview": "# Code Style\n\n## Formatting\n\nLinting is done through [ESLint](https://eslint.org/), code formatting is handled by [Prett"
},
{
"path": "docs/design-docs.md",
"chars": 217,
"preview": "# Design docs\n\nMost of these docs are in Google Docs for ease of modification and commenting.\n\n* [Story Editor e2e Testi"
},
{
"path": "docs/design-panel-push-update-flow.md",
"chars": 2531,
"preview": "# Design Panel Element Update Data Flow\n\nBelow is a rough outline of the data flow following input change updates in the"
},
{
"path": "docs/design-system.md",
"chars": 9717,
"preview": "# Design System\n\n## Overview\n\nWeb Stories exists as two apps right now, the editor and the dashboard. Both have their ow"
},
{
"path": "docs/devtools.md",
"chars": 252,
"preview": "# DevTools\n\nThere is a global shortcut (`Command+Shift+Option+J / Control+Shift+Alt+J`) for the editor DevTools.\n\n## Sha"
},
{
"path": "docs/e2e-tests.md",
"chars": 3624,
"preview": "# End-to-End Tests\n\nThis project leverages the [local Docker-based environment](./local-environment.md) to facilitate en"
},
{
"path": "docs/environment-variables.md",
"chars": 2379,
"preview": "# Environment Variables\n\nThroughout the project some environment variables are in use:\n\n## Application\n\n**DISABLE_PREVEN"
},
{
"path": "docs/external-template-creation.md",
"chars": 17515,
"preview": "# Creating a new template\n\n## Where things are stored\n\n- The **story JSON representation** for each template is stored i"
},
{
"path": "docs/feature-flags.md",
"chars": 1912,
"preview": "# Feature flags\n\nThe React apps leverage the [`flagged`](https://www.npmjs.com/package/flagged) library to allow guardin"
},
{
"path": "docs/getting-started.md",
"chars": 2901,
"preview": "# Getting Started\n\n## Requirements\n\nTo contribute to this plugin, you need the following tools installed on your compute"
},
{
"path": "docs/glossary.md",
"chars": 1498,
"preview": "# Glossary\n\n**Checklist**:\nThe checklist is a tab in the Design Panel that represents another, cleaner way of browsing t"
},
{
"path": "docs/integration-tests.md",
"chars": 5435,
"preview": "# Integration Tests\n\nKarma + Jasmine are used for running integration tests in the browser.\n\nMore details can be found i"
},
{
"path": "docs/local-environment.md",
"chars": 2118,
"preview": "# Local Environment\n\nCurrently, the two most common ways for setting up a local environment for working on the Web Stori"
},
{
"path": "docs/migrations.md",
"chars": 428,
"preview": "# Migrations\n\nMigration reducers can and should be written whenever the underlying data model is being changed.\n\nThis wa"
},
{
"path": "docs/onboarding.md",
"chars": 1889,
"preview": "# Onboarding\n\nShort checklist for onboarding of new contributors to the team.\n\nRequirements:\n\n* Email address\n* GitHub u"
},
{
"path": "docs/page-templates.md",
"chars": 3101,
"preview": "# Page Templates\n\nPage templates allow people to apply individual pages defined in templates to their story without choo"
},
{
"path": "docs/performance.md",
"chars": 6007,
"preview": "# Performance\n\nPerformance for the editor follows the [RAIL model](https://web.dev/rail/). Most of our in app interactio"
},
{
"path": "docs/quick-actions.md",
"chars": 7309,
"preview": "# Quick Actions\n\nSome actions are cumbersome in the editor as it's difficult to find them in the Design panel. The quick"
},
{
"path": "docs/right-click-menu.md",
"chars": 6390,
"preview": "# Right Click Menu (Context Menu)\n\nThe Right-click Menu provides additional functionality to the user. The actions displ"
},
{
"path": "docs/storybook.md",
"chars": 507,
"preview": "# Storybook\n\nA living components library is maintained using [Storybook](https://storybook.js.org/).\n\nThe latest version"
},
{
"path": "docs/svgs.md",
"chars": 1272,
"preview": "# SVGs\n\nSVGs (also known as icons) are needed in different formats across this project.\n\nThis project uses webpack's [as"
},
{
"path": "docs/testing-environments.md",
"chars": 1411,
"preview": "# Testing Environments\n\n## Staging Environment\n\nThe latest version of the plugin (i.e. current master branch) is up and "
},
{
"path": "docs/testing-qa.md",
"chars": 1719,
"preview": "# Manual Testing (QA)\n\n## ZIP Files\n\nEvery **pull request** automatically has a ZIP file attached to it that can be down"
},
{
"path": "docs/third-party-integration/dashboard/README.md",
"chars": 167,
"preview": "# Dashboard\n\n* [Getting Started](./getting-started.md)\n* [API Callbacks](./api-callbacks.md)\n* [Integration Layer](./int"
},
{
"path": "docs/third-party-integration/dashboard/api-callbacks.md",
"chars": 12867,
"preview": "# API Callbacks\n\nSide effects are added to the Dashboard by defining callbacks. One such callback is `fetchStories` whic"
},
{
"path": "docs/third-party-integration/dashboard/getting-started.md",
"chars": 2053,
"preview": "# Dashboard\n\nIf you want a companion dashboard to show stories created by the user or a list of story templates to choos"
},
{
"path": "docs/third-party-integration/dashboard/integration-layer.md",
"chars": 7450,
"preview": "# Integration Layer\n\nSimilar to the editor, the Dashboard can be integrated by configuring the `Dashboard` and other com"
},
{
"path": "docs/third-party-integration/dashboard/tutorial.md",
"chars": 5761,
"preview": "# Tutorial\n\nThis tutorial explains how to create a standalone story dashboard step by step. It covers implementing the f"
},
{
"path": "docs/third-party-integration/story-editor/README.md",
"chars": 170,
"preview": "# Story Editor\n\n* [Getting Started](./getting-started.md)\n* [API Callbacks](./api-callbacks.md)\n* [Integration Layer](./"
},
{
"path": "docs/third-party-integration/story-editor/api-callbacks.md",
"chars": 33162,
"preview": "# API Callbacks\n\nSimilar to the dashboard, side effects are added to the Story Editor by defining callbacks. One such ca"
},
{
"path": "docs/third-party-integration/story-editor/getting-started.md",
"chars": 2485,
"preview": "# Getting Started\n\nThe following documentation explains how to integrate the visual story editor with any platform. \n\nTh"
},
{
"path": "docs/third-party-integration/story-editor/integration-layer.md",
"chars": 18128,
"preview": "# Integration Layer\n\nThe story editor can be integrated with any platform by configuring the `StoryEditor` and other com"
},
{
"path": "docs/third-party-integration/story-editor/tutorial.md",
"chars": 10774,
"preview": "# Standalone Editor Tutorial\n\nThis tutorial explains how to create a standalone story editor using React that works with"
},
{
"path": "docs/unit-tests.md",
"chars": 4086,
"preview": "# Unit Tests\n\n## PHP\n\nThis project uses the [PHPUnit](https://phpunit.de/) testing framework to write unit and integrati"
},
{
"path": "docs/web-stories-embeds.md",
"chars": 13449,
"preview": "# Web Stories Embeds\n\nTheme developers can add varying degrees of support for Web Stories based on their requirements.\n\n"
},
{
"path": "docs/workflows.md",
"chars": 1262,
"preview": "# Workflows\n\n## Create plugin bundle\n\nTo create a build of the plugin for installing in WordPress as a ZIP package, run:"
},
{
"path": "includes/AMP/Canonical_Sanitizer.php",
"chars": 2975,
"preview": "<?php\n/**\n * Class Canonical_Sanitizer.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copy"
},
{
"path": "includes/AMP/Integration/AMP_Story_Sanitizer.php",
"chars": 2300,
"preview": "<?php\n/**\n * Class AMP_Story_Sanitizer.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copy"
},
{
"path": "includes/AMP/Meta_Sanitizer.php",
"chars": 4617,
"preview": "<?php\n/**\n * Class Meta_Sanitizer.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright"
},
{
"path": "includes/AMP/Optimization.php",
"chars": 6430,
"preview": "<?php\n/**\n * Class Optimization\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 20"
},
{
"path": "includes/AMP/Output_Buffer.php",
"chars": 6769,
"preview": "<?php\n/**\n * Class Output_Buffer\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2"
},
{
"path": "includes/AMP/Sanitization.php",
"chars": 18958,
"preview": "<?php\n/**\n * Class Sanitization\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 20"
},
{
"path": "includes/AMP/Story_Sanitizer.php",
"chars": 2260,
"preview": "<?php\n/**\n * Class Story_Sanitizer.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyrigh"
},
{
"path": "includes/AMP/Tag_And_Attribute_Sanitizer.php",
"chars": 1381,
"preview": "<?php\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may "
},
{
"path": "includes/AMP/Traits/Sanitization_Utils.php",
"chars": 21947,
"preview": "<?php\n/**\n * Trait Sanitization_Utils.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyr"
},
{
"path": "includes/AMP_Story_Player_Assets.php",
"chars": 2084,
"preview": "<?php\n/**\n * Class AMP_Story_Player_Assets.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @"
},
{
"path": "includes/AdSense.php",
"chars": 3296,
"preview": "<?php\n/**\n * Class AdSense\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Go"
},
{
"path": "includes/Ad_Manager.php",
"chars": 3259,
"preview": "<?php\n/**\n * Class Ad_Manager\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020"
},
{
"path": "includes/Admin/Activation_Notice.php",
"chars": 7629,
"preview": "<?php\n/**\n * Class Activation_Notice.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyri"
},
{
"path": "includes/Admin/Admin.php",
"chars": 7483,
"preview": "<?php\n/**\n * Admin class.\n *\n * Responsible for WordPress admin integration.\n *\n * @link https://github.com/googlef"
},
{
"path": "includes/Admin/Cross_Origin_Isolation.php",
"chars": 10407,
"preview": "<?php\n/**\n * Class Cross_Origin_Isolation.\n *\n * Check if editor screen, add cross origin header and add crossorigin att"
},
{
"path": "includes/Admin/Customizer.php",
"chars": 21734,
"preview": "<?php\n/**\n * Class Customizer\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020"
},
{
"path": "includes/Admin/Dashboard.php",
"chars": 16634,
"preview": "<?php\n/**\n * Dashboard class.\n *\n * Responsible for adding the stories dashboard to WordPress admin.\n *\n * @link ht"
},
{
"path": "includes/Admin/Editor.php",
"chars": 16202,
"preview": "<?php\n/**\n * Class Editor\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Goo"
},
{
"path": "includes/Admin/Google_Fonts.php",
"chars": 2145,
"preview": "<?php\n/**\n * Class Google_Fonts.\n *\n * Registers Google fonts for admin screens.\n *\n * @link https://github.com/goo"
},
{
"path": "includes/Admin/Meta_Boxes.php",
"chars": 4837,
"preview": "<?php\n/**\n * Class Meta_Boxes.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 202"
},
{
"path": "includes/Admin/PluginActionLinks.php",
"chars": 2223,
"preview": "<?php\n/**\n * PluginActionLinks class.\n *\n * Updates the plugin action links for the plugin.\n *\n * @link https://git"
},
{
"path": "includes/Admin/PluginRowMeta.php",
"chars": 2589,
"preview": "<?php\n/**\n * PluginRowMeta class.\n *\n * Updates the plugin row meta for the plugin.\n *\n * @link https://github.com/"
},
{
"path": "includes/Admin/Site_Health.php",
"chars": 7440,
"preview": "<?php\n/**\n * Site Health Class.\n *\n * Adds tests and debugging information for Site Health.\n *\n * @link https://git"
},
{
"path": "includes/Admin/TinyMCE.php",
"chars": 5455,
"preview": "<?php\n/**\n * TinyMCE Class.\n *\n * Necessary operations for classic editor compatibility.\n *\n * @link https://github"
},
{
"path": "includes/Analytics.php",
"chars": 8176,
"preview": "<?php\n/**\n * Class Analytics\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 "
},
{
"path": "includes/Assets.php",
"chars": 16236,
"preview": "<?php\n/**\n * Class Assets\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Goo"
},
{
"path": "includes/Block/Web_Stories_Block.php",
"chars": 12507,
"preview": "<?php\n/**\n * Class Web_Stories_Block.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyri"
},
{
"path": "includes/Context.php",
"chars": 3829,
"preview": "<?php\n/**\n * Class Context\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Go"
},
{
"path": "includes/Database_Upgrader.php",
"chars": 5668,
"preview": "<?php\n/**\n * Class Database_Upgrader\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyrig"
},
{
"path": "includes/Decoder.php",
"chars": 1762,
"preview": "<?php\n/**\n * Class Decoder\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Go"
},
{
"path": "includes/Demo_Content.php",
"chars": 6605,
"preview": "<?php\n/**\n * Demo_Content class.\n *\n * Used for getting demo content.\n *\n * @link https://github.com/googleforcreat"
},
{
"path": "includes/Discovery.php",
"chars": 14944,
"preview": "<?php\n/**\n * Class Discovery.\n *\n * Responsible for improved discovery of stories on the web.\n *\n * @link https://g"
},
{
"path": "includes/Embed_Base.php",
"chars": 5553,
"preview": "<?php\n/**\n * Class Embed_Block.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 20"
},
{
"path": "includes/Exception/FailedToMakeInstance.php",
"chars": 5257,
"preview": "<?php\n/**\n * Exception FailedToMakeInstance.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser"
},
{
"path": "includes/Exception/InvalidEventProperties.php",
"chars": 2879,
"preview": "<?php\n/**\n * Exception InvalidEventProperties.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n "
},
{
"path": "includes/Exception/InvalidService.php",
"chars": 1993,
"preview": "<?php\n/**\n * Exception InvalidService.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @l"
},
{
"path": "includes/Exception/SanitizationException.php",
"chars": 1359,
"preview": "<?php\n/**\n * Exception SanitizationException.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n *"
},
{
"path": "includes/Exception/WebStoriesException.php",
"chars": 1213,
"preview": "<?php\n/**\n * Interface WebStoriesException.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @"
},
{
"path": "includes/Experiments.php",
"chars": 9626,
"preview": "<?php\n/**\n * Class Experiments\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 202"
},
{
"path": "includes/Font_Post_Type.php",
"chars": 3692,
"preview": "<?php\n/**\n * Class Font_Post_Type.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright"
},
{
"path": "includes/Infrastructure/Conditional.php",
"chars": 1027,
"preview": "<?php\n/**\n * Interface Conditional.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @lice"
},
{
"path": "includes/Infrastructure/Delayed.php",
"chars": 1211,
"preview": "<?php\n/**\n * Interface Delayed.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license "
},
{
"path": "includes/Infrastructure/HasMeta.php",
"chars": 471,
"preview": "<?php\n/**\n * Interface HasMeta.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 20"
},
{
"path": "includes/Infrastructure/HasRequirements.php",
"chars": 1226,
"preview": "<?php\n/**\n * Interface HasRequirements.\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, V"
},
{
"path": "includes/Infrastructure/Injector/FallbackInstantiator.php",
"chars": 1226,
"preview": "<?php\n/**\n * Final class FallbackInstantiator.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n "
},
{
"path": "includes/Infrastructure/Injector/InjectionChain.php",
"chars": 3226,
"preview": "<?php\n/**\n * Final class InjectionChain.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * "
},
{
"path": "includes/Infrastructure/Injector/SimpleInjector.php",
"chars": 15241,
"preview": "<?php\n/**\n * Final class SimpleInjector.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * "
},
{
"path": "includes/Infrastructure/Injector.php",
"chars": 4224,
"preview": "<?php\n/**\n * Interface Injector.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license"
},
{
"path": "includes/Infrastructure/Instantiator.php",
"chars": 1132,
"preview": "<?php\n/**\n * Interface Instantiator.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @lic"
},
{
"path": "includes/Infrastructure/Plugin.php",
"chars": 1349,
"preview": "<?php\n/**\n * Interface Plugin\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license "
},
{
"path": "includes/Infrastructure/PluginActivationAware.php",
"chars": 993,
"preview": "<?php\n/**\n * Interface PluginActivationAware.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesse"
},
{
"path": "includes/Infrastructure/PluginDeactivationAware.php",
"chars": 1009,
"preview": "<?php\n/**\n * Interface PluginDeactivationAware.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schles"
},
{
"path": "includes/Infrastructure/PluginUninstallAware.php",
"chars": 1231,
"preview": "<?php\n/**\n * Interface PluginUninstallAware.\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache Licen"
},
{
"path": "includes/Infrastructure/Registerable.php",
"chars": 960,
"preview": "<?php\n/**\n * Interface Registerable.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @lic"
},
{
"path": "includes/Infrastructure/Service.php",
"chars": 659,
"preview": "<?php\n/**\n * Interface Service.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license "
},
{
"path": "includes/Infrastructure/ServiceBasedPlugin.php",
"chars": 26948,
"preview": "<?php\n/**\n * Class ServiceBasedPlugin.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @l"
},
{
"path": "includes/Infrastructure/ServiceContainer/LazilyInstantiatedService.php",
"chars": 1643,
"preview": "<?php\n/**\n * Final class LazilyInstantiatedService.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Sc"
},
{
"path": "includes/Infrastructure/ServiceContainer/SimpleServiceContainer.php",
"chars": 2286,
"preview": "<?php\n/**\n * Final class SimpleServiceContainer.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schle"
},
{
"path": "includes/Infrastructure/ServiceContainer.php",
"chars": 1817,
"preview": "<?php\n/**\n * Interface ServiceContainer.\n *\n * @link https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * "
},
{
"path": "includes/Infrastructure/SiteInitializationAware.php",
"chars": 780,
"preview": "<?php\n/**\n * Interface SiteInitializationAware.\n *\n * @link https://github.com/googleforcreators/web-stories-wp\n *\n"
}
]
// ... and 4293 more files (download for full content)
About this extraction
This page contains the full source code of the GoogleForCreators/web-stories-wp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 4493 files (25.1 MB), approximately 6.8M tokens, and a symbol index with 7873 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.