main 65b196460fbf cached
4493 files
25.1 MB
6.8M tokens
7873 symbols
1 requests
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
Download .txt
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/
│   │    
Download .txt
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[![Latest Release)](https://img.shields.io/github/v/rel"
  },
  {
    "path": "SECURITY.md",
    "chars": 270,
    "preview": "# Security Policy\n\n## Supported Versions\n\nWe support the latest stable version of the plugin with security updates.\n\n## "
  },
  {
    "path": "__mocks__/colorthief.js",
    "chars": 626,
    "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__/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![Canvas Layers](https://user-images.githubusercontent.com/726049/72654503-bfffe780-3944-11ea-912c-"
  },
  {
    "path": "docs/cdn.md",
    "chars": 1968,
    "preview": "# CDN\n\nLarge assets to be used by the plugin are hosted on the [wp.stories.google](https://wp.stories.google) 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.

Copied to clipboard!