summaryrefslogtreecommitdiffstats
path: root/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx')
-rw-r--r--browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx110
1 files changed, 110 insertions, 0 deletions
diff --git a/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx b/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx
new file mode 100644
index 0000000000..71714d8d25
--- /dev/null
+++ b/browser/components/storybook/.storybook/addon-fluent/FluentPanel.jsx
@@ -0,0 +1,110 @@
+/* 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/. */
+
+// eslint-disable-next-line no-unused-vars
+import React, { useEffect, useState } from "react";
+import { addons, useGlobals, useStorybookApi } from "@storybook/manager-api";
+// eslint-disable-next-line no-unused-vars
+import { AddonPanel, Table, Form } from "@storybook/components";
+import { FLUENT_CHANGED, FLUENT_SET_STRINGS } from "./constants.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "./fluent-panel.css";
+
+export const FluentPanel = ({ active }) => {
+ const [fileName, setFileName] = useState(null);
+ const [strings, setStrings] = useState([]);
+ const [{ fluentStrings }, updateGlobals] = useGlobals();
+ const channel = addons.getChannel();
+ const api = useStorybookApi();
+
+ useEffect(() => {
+ channel.on(FLUENT_CHANGED, handleFluentChanged);
+ return () => {
+ channel.off(FLUENT_CHANGED, handleFluentChanged);
+ };
+ }, [channel]);
+
+ const handleFluentChanged = (nextStrings, fluentFile) => {
+ setFileName(fluentFile);
+ setStrings(nextStrings);
+ };
+
+ const onInput = e => {
+ let nextStrings = [];
+ for (let [key, value] of strings) {
+ if (key == e.target.name) {
+ let stringValue = e.target.value;
+ if (stringValue.startsWith(".")) {
+ stringValue = "\n" + stringValue;
+ }
+ nextStrings.push([key, stringValue]);
+ } else {
+ nextStrings.push([key, value]);
+ }
+ }
+ let stringified = nextStrings
+ .map(([key, value]) => `${key} = ${value}`)
+ .join("\n");
+ channel.emit(FLUENT_SET_STRINGS, stringified);
+ updateGlobals({
+ fluentStrings: { ...fluentStrings, [fileName]: nextStrings },
+ });
+ return { fileName, strings };
+ };
+
+ const addonTemplate = () => {
+ if (strings.length === 0) {
+ return (
+ <AddonPanel active={!!active} api={api}>
+ <div className="addon-panel-body">
+ <div className="addon-panel-message">
+ This story is not configured to use Fluent.
+ </div>
+ </div>
+ </AddonPanel>
+ );
+ }
+
+ return (
+ <AddonPanel active={!!active} api={api}>
+ <div className="addon-panel-body">
+ <Table aria-hidden="false" className="addon-panel-table">
+ <thead className="addon-panel-table-head">
+ <tr>
+ <th>
+ <span>Identifier</span>
+ </th>
+ <th>
+ <span>String</span>
+ </th>
+ </tr>
+ </thead>
+ <tbody className="addon-panel-table-body">
+ {strings.map(([identifier, value]) => (
+ <tr key={identifier}>
+ <td>
+ <span>{identifier}</span>
+ </td>
+ <td>
+ <Form.Textarea
+ name={identifier}
+ onInput={onInput}
+ defaultValue={value
+ .trim()
+ .split("\n")
+ .map(s => s.trim())
+ .join("\n")}
+ ></Form.Textarea>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </Table>
+ </div>
+ </AddonPanel>
+ );
+ };
+
+ return addonTemplate();
+};