/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { useEffect, useGlobals, addons } from "@storybook/addons"; import { DIRECTIONS, DIRECTION_BY_STRATEGY, UPDATE_STRATEGY_EVENT, FLUENT_CHANGED, } from "./constants.mjs"; import { provideFluent } from "../fluent-utils.mjs"; /** * withPseudoLocalization is a Storybook decorator that handles emitting an * event to update translations when a new pseudo localization strategy is * applied. It also handles setting a "dir" attribute on the root element in the * Storybook iframe. * * @param {Function} StoryFn - Provided by Storybook, used to render the story. * @param {Object} context - Provided by Storybook, data about the story. * @returns {Function} StoryFn with a modified "dir" attr set. */ export const withPseudoLocalization = (StoryFn, context) => { const [{ pseudoStrategy }] = useGlobals(); const direction = DIRECTION_BY_STRATEGY[pseudoStrategy] || DIRECTIONS.ltr; const isInDocs = context.viewMode === "docs"; const channel = addons.getChannel(); useEffect(() => { if (pseudoStrategy) { channel.emit(UPDATE_STRATEGY_EVENT, pseudoStrategy); } }, [pseudoStrategy]); useEffect(() => { if (isInDocs) { document.documentElement.setAttribute("dir", DIRECTIONS.ltr); let storyElements = document.querySelectorAll(".docs-story"); storyElements.forEach(element => element.setAttribute("dir", direction)); } else { document.documentElement.setAttribute("dir", direction); } }, [direction, isInDocs]); return StoryFn(); }; /** * withFluentStrings is a Storybook decorator that handles emitting an * event to update the Fluent strings shown in the Fluent panel. * * @param {Function} StoryFn - Provided by Storybook, used to render the story. * @param {Object} context - Provided by Storybook, data about the story. * @returns {Function} StoryFn unmodified. */ export const withFluentStrings = (StoryFn, context) => { const [{ fluentStrings }, updateGlobals] = useGlobals(); const channel = addons.getChannel(); const fileName = context.component + ".ftl"; let strings = []; if (context.parameters?.fluent && fileName) { if (fluentStrings.hasOwnProperty(fileName)) { strings = fluentStrings[fileName]; } else { let resource = provideFluent(context.parameters.fluent, fileName); for (let message of resource.body) { strings.push([ message.id, [ message.value, ...Object.entries(message.attributes).map( ([key, value]) => ` .${key} = ${value}` ), ].join("\n"), ]); } updateGlobals({ fluentStrings: { ...fluentStrings, [fileName]: strings }, }); } } channel.emit(FLUENT_CHANGED, strings); return StoryFn(); };