@formatjs/editor 1.1.48 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +393 -2
- package/index.d.ts +143 -3
- package/index.js +334 -118
- package/index.js.map +1 -0
- package/package.json +29 -21
- package/ui.d.ts +177 -0
- package/ui.js +212 -0
- package/ui.js.map +1 -0
- package/header.d.ts +0 -6
- package/header.d.ts.map +0 -1
- package/header.js +0 -16
- package/index.d.ts.map +0 -1
- package/lib/header.d.ts +0 -6
- package/lib/header.d.ts.map +0 -1
- package/lib/header.js +0 -13
- package/lib/index.d.ts +0 -4
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -116
- package/lib/main.d.ts +0 -2
- package/lib/main.d.ts.map +0 -1
- package/lib/main.js +0 -4
- package/lib/message.d.ts +0 -7
- package/lib/message.d.ts.map +0 -1
- package/lib/message.js +0 -45
- package/lib/messages.d.ts +0 -10
- package/lib/messages.d.ts.map +0 -1
- package/lib/messages.js +0 -21
- package/lib/types.d.ts +0 -6
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -1
- package/main.d.ts +0 -2
- package/main.d.ts.map +0 -1
- package/main.js +0 -7
- package/message.d.ts +0 -7
- package/message.d.ts.map +0 -1
- package/message.js +0 -47
- package/messages.d.ts +0 -10
- package/messages.d.ts.map +0 -1
- package/messages.js +0 -24
- package/types.d.ts +0 -6
- package/types.d.ts.map +0 -1
- package/types.js +0 -2
package/ui.d.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { ComponentType, ReactNode } from "react";
|
|
2
|
+
import "@formatjs/icu-messageformat-parser";
|
|
3
|
+
//#region packages/editor/validation.d.ts
|
|
4
|
+
type TranslationValidationError = "empty" | "invalid-source" | "invalid-translation" | "structure";
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region packages/editor/workflow.d.ts
|
|
7
|
+
interface SourceLocation {
|
|
8
|
+
file: string;
|
|
9
|
+
start?: number;
|
|
10
|
+
end?: number;
|
|
11
|
+
}
|
|
12
|
+
interface EditorMessage {
|
|
13
|
+
id: string;
|
|
14
|
+
defaultMessage: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
catalogs?: readonly string[];
|
|
17
|
+
locations?: readonly SourceLocation[];
|
|
18
|
+
translations: Readonly<Record<string, string | undefined>>;
|
|
19
|
+
}
|
|
20
|
+
type TranslationSaveResult<TResult = void> = {
|
|
21
|
+
status: "saved";
|
|
22
|
+
value: TResult;
|
|
23
|
+
} | {
|
|
24
|
+
status: "failed";
|
|
25
|
+
error: Error;
|
|
26
|
+
} | {
|
|
27
|
+
status: "invalid";
|
|
28
|
+
validationError: TranslationValidationError;
|
|
29
|
+
} | {
|
|
30
|
+
status: "skipped";
|
|
31
|
+
reason: "unavailable" | "unchanged" | "pending";
|
|
32
|
+
};
|
|
33
|
+
/** A render snapshot and actions for one message/locale pair. */
|
|
34
|
+
interface TranslationDraftState<TContext = void, TResult = void> {
|
|
35
|
+
readonly value: string;
|
|
36
|
+
readonly baseline: string;
|
|
37
|
+
readonly validationError: TranslationValidationError | null;
|
|
38
|
+
readonly changed: boolean;
|
|
39
|
+
readonly isSaving: boolean;
|
|
40
|
+
readonly saveError: Error | null;
|
|
41
|
+
readonly saved: boolean;
|
|
42
|
+
setTranslation: (value: string) => void;
|
|
43
|
+
reset: () => void;
|
|
44
|
+
save: (context?: TContext) => Promise<TranslationSaveResult<TResult>>;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region packages/editor/ui.d.ts
|
|
48
|
+
export interface EditorButtonProps {
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
/** Called once per activation, without a DOM event; disabled controls must not call it. */
|
|
51
|
+
onPress: () => void;
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
variant: "primary" | "secondary";
|
|
54
|
+
}
|
|
55
|
+
export interface EditorInputProps {
|
|
56
|
+
id: string;
|
|
57
|
+
value: string;
|
|
58
|
+
/** Reports the complete next string value; never a DOM event. */
|
|
59
|
+
onValueChange: (value: string) => void;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
"aria-invalid"?: boolean;
|
|
62
|
+
"aria-describedby"?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface EditorTextInputProps extends EditorInputProps {
|
|
65
|
+
type: "text" | "search";
|
|
66
|
+
}
|
|
67
|
+
export interface EditorTextAreaProps extends EditorInputProps {
|
|
68
|
+
/** Visible rows when supported by the control; defaults to six. */
|
|
69
|
+
rows?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface EditorMessageRowProps {
|
|
72
|
+
children: ReactNode;
|
|
73
|
+
selected: boolean;
|
|
74
|
+
/** Activates this row without changing controlled selection itself. */
|
|
75
|
+
onSelect: () => void;
|
|
76
|
+
}
|
|
77
|
+
export interface EditorPanelProps {
|
|
78
|
+
children: ReactNode;
|
|
79
|
+
label: string;
|
|
80
|
+
kind: "source" | "translation";
|
|
81
|
+
}
|
|
82
|
+
export interface EditorLayoutProps {
|
|
83
|
+
toolbar: ReactNode;
|
|
84
|
+
navigation: ReactNode;
|
|
85
|
+
content: ReactNode;
|
|
86
|
+
}
|
|
87
|
+
/** Define adapters outside render so controls retain focus across edits. */
|
|
88
|
+
export interface EditorComponents {
|
|
89
|
+
Button: ComponentType<EditorButtonProps>;
|
|
90
|
+
TextInput: ComponentType<EditorTextInputProps>;
|
|
91
|
+
TextArea: ComponentType<EditorTextAreaProps>;
|
|
92
|
+
MessageRow: ComponentType<EditorMessageRowProps>;
|
|
93
|
+
Panel: ComponentType<EditorPanelProps>;
|
|
94
|
+
Layout: ComponentType<EditorLayoutProps>;
|
|
95
|
+
}
|
|
96
|
+
export interface EditorLabels {
|
|
97
|
+
search: string;
|
|
98
|
+
messages: string;
|
|
99
|
+
source: string;
|
|
100
|
+
noMessages: string;
|
|
101
|
+
noSelection: string;
|
|
102
|
+
loading: string;
|
|
103
|
+
copySource: string;
|
|
104
|
+
reset: string;
|
|
105
|
+
save: string;
|
|
106
|
+
saving: string;
|
|
107
|
+
saved: string;
|
|
108
|
+
unsaved: string;
|
|
109
|
+
unchanged: string;
|
|
110
|
+
validation: Record<TranslationValidationError, string>;
|
|
111
|
+
}
|
|
112
|
+
export type EditorLabelOverrides = Partial<Omit<EditorLabels, "validation">> & {
|
|
113
|
+
validation?: Partial<EditorLabels["validation"]>;
|
|
114
|
+
};
|
|
115
|
+
/** Unstyled native controls; no CSS, icons, or localization provider is required. */
|
|
116
|
+
export declare const nativeEditorComponents: EditorComponents;
|
|
117
|
+
export interface EditorDesignSystemProviderProps {
|
|
118
|
+
/** Overrides inherit unspecified components from the nearest provider. */
|
|
119
|
+
components: Partial<EditorComponents>;
|
|
120
|
+
children: ReactNode;
|
|
121
|
+
}
|
|
122
|
+
/** Configure a tree once; sibling providers remain independent. */
|
|
123
|
+
export declare function EditorDesignSystemProvider({ components, children }: EditorDesignSystemProviderProps): ReactNode;
|
|
124
|
+
/** Read the resolved controls, including native defaults outside a provider. */
|
|
125
|
+
export declare function useEditorDesignSystem(): Readonly<EditorComponents>;
|
|
126
|
+
interface ViewOptions {
|
|
127
|
+
labels?: EditorLabelOverrides;
|
|
128
|
+
}
|
|
129
|
+
export type EditorViewMessage = Pick<EditorMessage, "id" | "defaultMessage" | "description">;
|
|
130
|
+
export interface EditorSearch {
|
|
131
|
+
value: string;
|
|
132
|
+
onValueChange: (value: string) => void;
|
|
133
|
+
}
|
|
134
|
+
export interface MessageListProps extends ViewOptions {
|
|
135
|
+
messages: readonly EditorViewMessage[];
|
|
136
|
+
selectedId?: string;
|
|
137
|
+
onSelect: (id: string) => void;
|
|
138
|
+
search?: EditorSearch;
|
|
139
|
+
loading?: boolean;
|
|
140
|
+
pagination?: ReactNode;
|
|
141
|
+
}
|
|
142
|
+
/** Controlled list: it never filters, paginates, fetches, or changes selection itself. */
|
|
143
|
+
export declare function MessageList({ messages, selectedId, onSelect, search, loading, pagination, labels }: MessageListProps): ReactNode;
|
|
144
|
+
export interface SourceMessageProps extends ViewOptions {
|
|
145
|
+
message: EditorViewMessage;
|
|
146
|
+
preview?: ReactNode;
|
|
147
|
+
context?: ReactNode;
|
|
148
|
+
}
|
|
149
|
+
export declare function SourceMessage({ message, preview, context, labels }: SourceMessageProps): ReactNode;
|
|
150
|
+
export type TranslationFieldDraft = Pick<TranslationDraftState, "value" | "validationError" | "changed" | "isSaving" | "saveError" | "saved" | "setTranslation" | "reset">;
|
|
151
|
+
export interface TranslationFieldProps extends ViewOptions {
|
|
152
|
+
locale: string;
|
|
153
|
+
/** Human-readable label; defaults to the locale identifier. */
|
|
154
|
+
label?: string;
|
|
155
|
+
source: string;
|
|
156
|
+
draft: TranslationFieldDraft;
|
|
157
|
+
/** The caller owns confirmation, context, persistence, and receipt presentation. */
|
|
158
|
+
onSave?: () => void;
|
|
159
|
+
/** Overrides the default copy/reset/save actions, including with null. */
|
|
160
|
+
actions?: ReactNode;
|
|
161
|
+
preview?: ReactNode;
|
|
162
|
+
}
|
|
163
|
+
export declare function TranslationField({ locale, label, source, draft, onSave, actions, preview, labels }: TranslationFieldProps): ReactNode;
|
|
164
|
+
export type EditorTranslation = Omit<TranslationFieldProps, "source" | "labels">;
|
|
165
|
+
export interface TranslationEditorViewProps extends Omit<MessageListProps, "selectedId"> {
|
|
166
|
+
/** May be outside the loaded list, e.g. during a server-side page change. */
|
|
167
|
+
selectedMessage?: EditorViewMessage;
|
|
168
|
+
translations: readonly EditorTranslation[];
|
|
169
|
+
filters?: ReactNode;
|
|
170
|
+
context?: ReactNode;
|
|
171
|
+
sourcePreview?: ReactNode;
|
|
172
|
+
notice?: ReactNode;
|
|
173
|
+
}
|
|
174
|
+
/** A stateless composition over caller-owned navigation and locale drafts. */
|
|
175
|
+
export declare function TranslationEditorView({ selectedMessage, translations, filters, context, sourcePreview, notice, labels, ...list }: TranslationEditorViewProps): ReactNode;
|
|
176
|
+
//#endregion
|
|
177
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/ui.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { createContext, createElement, useContext, useId, useMemo } from "react";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region packages/editor/ui.tsx
|
|
4
|
+
const defaultLabels = {
|
|
5
|
+
search: "Search messages",
|
|
6
|
+
messages: "Messages",
|
|
7
|
+
source: "Source message",
|
|
8
|
+
noMessages: "No matching messages",
|
|
9
|
+
noSelection: "Select a message",
|
|
10
|
+
loading: "Loading messages…",
|
|
11
|
+
copySource: "Copy source",
|
|
12
|
+
reset: "Reset",
|
|
13
|
+
save: "Save translation",
|
|
14
|
+
saving: "Saving…",
|
|
15
|
+
saved: "Translation saved.",
|
|
16
|
+
unsaved: "Unsaved changes",
|
|
17
|
+
unchanged: "No unsaved changes",
|
|
18
|
+
validation: {
|
|
19
|
+
empty: "Enter a translation before saving.",
|
|
20
|
+
"invalid-source": "The source contains invalid ICU syntax.",
|
|
21
|
+
"invalid-translation": "The translation contains invalid ICU syntax.",
|
|
22
|
+
structure: "Preserve ICU arguments, tags, formatting styles, and selector branches."
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function resolveLabels(labels) {
|
|
26
|
+
return {
|
|
27
|
+
...defaultLabels,
|
|
28
|
+
...labels,
|
|
29
|
+
validation: {
|
|
30
|
+
...defaultLabels.validation,
|
|
31
|
+
...labels?.validation
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Unstyled native controls; no CSS, icons, or localization provider is required. */
|
|
36
|
+
const nativeEditorComponents = {
|
|
37
|
+
Button: ({ children, onPress, disabled }) => /* @__PURE__ */ jsx("button", {
|
|
38
|
+
type: "button",
|
|
39
|
+
disabled,
|
|
40
|
+
onClick: () => onPress(),
|
|
41
|
+
children
|
|
42
|
+
}),
|
|
43
|
+
TextInput: ({ onValueChange, ...props }) => /* @__PURE__ */ jsx("input", {
|
|
44
|
+
...props,
|
|
45
|
+
onChange: (event) => onValueChange(event.target.value)
|
|
46
|
+
}),
|
|
47
|
+
TextArea: ({ onValueChange, rows = 6, ...props }) => /* @__PURE__ */ jsx("textarea", {
|
|
48
|
+
...props,
|
|
49
|
+
rows,
|
|
50
|
+
onChange: (event) => onValueChange(event.target.value)
|
|
51
|
+
}),
|
|
52
|
+
MessageRow: ({ children, selected, onSelect }) => /* @__PURE__ */ jsx("button", {
|
|
53
|
+
type: "button",
|
|
54
|
+
"aria-current": selected ? "true" : void 0,
|
|
55
|
+
onClick: () => onSelect(),
|
|
56
|
+
children
|
|
57
|
+
}),
|
|
58
|
+
Panel: ({ children, label }) => /* @__PURE__ */ jsx("section", {
|
|
59
|
+
"aria-label": label,
|
|
60
|
+
children
|
|
61
|
+
}),
|
|
62
|
+
Layout: ({ toolbar, navigation, content }) => /* @__PURE__ */ jsxs("div", { children: [toolbar, /* @__PURE__ */ jsxs("div", { children: [navigation, content] })] })
|
|
63
|
+
};
|
|
64
|
+
const EditorDesignSystemContext = createContext(nativeEditorComponents);
|
|
65
|
+
/** Configure a tree once; sibling providers remain independent. */
|
|
66
|
+
function EditorDesignSystemProvider({ components, children }) {
|
|
67
|
+
const parent = useEditorDesignSystem();
|
|
68
|
+
const value = useMemo(() => ({
|
|
69
|
+
...parent,
|
|
70
|
+
...components
|
|
71
|
+
}), [parent, components]);
|
|
72
|
+
return /* @__PURE__ */ jsx(EditorDesignSystemContext, {
|
|
73
|
+
value,
|
|
74
|
+
children
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/** Read the resolved controls, including native defaults outside a provider. */
|
|
78
|
+
function useEditorDesignSystem() {
|
|
79
|
+
return useContext(EditorDesignSystemContext);
|
|
80
|
+
}
|
|
81
|
+
/** Controlled list: it never filters, paginates, fetches, or changes selection itself. */
|
|
82
|
+
function MessageList({ messages, selectedId, onSelect, search, loading = false, pagination, labels }) {
|
|
83
|
+
const { TextInput, MessageRow } = useEditorDesignSystem();
|
|
84
|
+
const text = resolveLabels(labels);
|
|
85
|
+
const searchId = useId();
|
|
86
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
87
|
+
"aria-label": text.messages,
|
|
88
|
+
"aria-busy": loading,
|
|
89
|
+
children: [
|
|
90
|
+
search && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
91
|
+
htmlFor: searchId,
|
|
92
|
+
children: text.search
|
|
93
|
+
}), /* @__PURE__ */ jsx(TextInput, {
|
|
94
|
+
id: searchId,
|
|
95
|
+
type: "search",
|
|
96
|
+
value: search.value,
|
|
97
|
+
onValueChange: search.onValueChange
|
|
98
|
+
})] }),
|
|
99
|
+
loading && /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("output", { children: text.loading }) }),
|
|
100
|
+
/* @__PURE__ */ jsx("ul", { children: messages.map((message) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(MessageRow, {
|
|
101
|
+
selected: message.id === selectedId,
|
|
102
|
+
onSelect: () => onSelect(message.id),
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsx("span", { children: message.defaultMessage }),
|
|
105
|
+
" ",
|
|
106
|
+
/* @__PURE__ */ jsx("code", { children: message.id })
|
|
107
|
+
]
|
|
108
|
+
}) }, message.id)) }),
|
|
109
|
+
!loading && messages.length === 0 && /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("output", { children: text.noMessages }) }),
|
|
110
|
+
pagination
|
|
111
|
+
]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function SourceMessage({ message, preview, context, labels }) {
|
|
115
|
+
const { Panel } = useEditorDesignSystem();
|
|
116
|
+
const text = resolveLabels(labels);
|
|
117
|
+
return /* @__PURE__ */ jsxs(Panel, {
|
|
118
|
+
kind: "source",
|
|
119
|
+
label: text.source,
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ jsx("h2", { children: text.source }),
|
|
122
|
+
/* @__PURE__ */ jsx("code", { children: message.id }),
|
|
123
|
+
preview ?? /* @__PURE__ */ jsx("pre", { children: message.defaultMessage }),
|
|
124
|
+
message.description && /* @__PURE__ */ jsx("p", { children: message.description }),
|
|
125
|
+
context
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function TranslationField({ locale, label = locale, source, draft, onSave, actions, preview, labels }) {
|
|
130
|
+
const { Panel, TextArea, Button } = useEditorDesignSystem();
|
|
131
|
+
const text = resolveLabels(labels);
|
|
132
|
+
const id = useId();
|
|
133
|
+
const errorId = `${id}-error`;
|
|
134
|
+
const statusId = `${id}-status`;
|
|
135
|
+
const validation = draft.validationError ? text.validation[draft.validationError] : null;
|
|
136
|
+
const error = validation ?? draft.saveError?.message;
|
|
137
|
+
return /* @__PURE__ */ jsxs(Panel, {
|
|
138
|
+
kind: "translation",
|
|
139
|
+
label,
|
|
140
|
+
children: [
|
|
141
|
+
/* @__PURE__ */ jsx("label", {
|
|
142
|
+
htmlFor: id,
|
|
143
|
+
children: label
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ jsx(TextArea, {
|
|
146
|
+
id,
|
|
147
|
+
value: draft.value,
|
|
148
|
+
onValueChange: draft.setTranslation,
|
|
149
|
+
"aria-invalid": !!validation,
|
|
150
|
+
"aria-describedby": error ? `${errorId} ${statusId}` : statusId
|
|
151
|
+
}),
|
|
152
|
+
error && /* @__PURE__ */ jsx("p", {
|
|
153
|
+
id: errorId,
|
|
154
|
+
role: "alert",
|
|
155
|
+
children: error
|
|
156
|
+
}),
|
|
157
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("output", {
|
|
158
|
+
id: statusId,
|
|
159
|
+
children: draft.isSaving ? text.saving : draft.saved ? text.saved : draft.changed ? text.unsaved : text.unchanged
|
|
160
|
+
}) }),
|
|
161
|
+
preview,
|
|
162
|
+
actions !== void 0 ? actions : /* @__PURE__ */ jsxs("div", { children: [
|
|
163
|
+
/* @__PURE__ */ jsx(Button, {
|
|
164
|
+
variant: "secondary",
|
|
165
|
+
disabled: draft.isSaving,
|
|
166
|
+
onPress: () => draft.setTranslation(source),
|
|
167
|
+
children: text.copySource
|
|
168
|
+
}),
|
|
169
|
+
/* @__PURE__ */ jsx(Button, {
|
|
170
|
+
variant: "secondary",
|
|
171
|
+
disabled: !draft.changed || draft.isSaving,
|
|
172
|
+
onPress: draft.reset,
|
|
173
|
+
children: text.reset
|
|
174
|
+
}),
|
|
175
|
+
onSave && /* @__PURE__ */ jsx(Button, {
|
|
176
|
+
variant: "primary",
|
|
177
|
+
disabled: !draft.changed || !!draft.validationError || draft.isSaving,
|
|
178
|
+
onPress: onSave,
|
|
179
|
+
children: draft.isSaving ? text.saving : text.save
|
|
180
|
+
})
|
|
181
|
+
] })
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/** A stateless composition over caller-owned navigation and locale drafts. */
|
|
186
|
+
function TranslationEditorView({ selectedMessage, translations, filters, context, sourcePreview, notice, labels, ...list }) {
|
|
187
|
+
const { Layout } = useEditorDesignSystem();
|
|
188
|
+
const text = resolveLabels(labels);
|
|
189
|
+
return /* @__PURE__ */ jsx(Layout, {
|
|
190
|
+
toolbar: filters,
|
|
191
|
+
navigation: /* @__PURE__ */ jsx(MessageList, {
|
|
192
|
+
...list,
|
|
193
|
+
selectedId: selectedMessage?.id,
|
|
194
|
+
labels
|
|
195
|
+
}),
|
|
196
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [notice, selectedMessage ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SourceMessage, {
|
|
197
|
+
message: selectedMessage,
|
|
198
|
+
preview: sourcePreview,
|
|
199
|
+
context,
|
|
200
|
+
labels
|
|
201
|
+
}), translations.map((translation) => /* @__PURE__ */ createElement(TranslationField, {
|
|
202
|
+
...translation,
|
|
203
|
+
key: `${selectedMessage.id}:${translation.locale}`,
|
|
204
|
+
source: selectedMessage.defaultMessage,
|
|
205
|
+
labels
|
|
206
|
+
}))] }) : /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("output", { children: text.noSelection }) })] })
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
export { EditorDesignSystemProvider, MessageList, SourceMessage, TranslationEditorView, TranslationField, nativeEditorComponents, useEditorDesignSystem };
|
|
211
|
+
|
|
212
|
+
//# sourceMappingURL=ui.js.map
|
package/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","names":[],"sources":["../ui.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useId,\n useMemo,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport type {\n EditorMessage,\n TranslationDraftState,\n} from '#packages/editor/workflow.js'\nimport type {TranslationValidationError} from '#packages/editor/validation.js'\n\nexport interface EditorButtonProps {\n children: ReactNode\n /** Called once per activation, without a DOM event; disabled controls must not call it. */\n onPress: () => void\n disabled?: boolean\n variant: 'primary' | 'secondary'\n}\nexport interface EditorInputProps {\n id: string\n value: string\n /** Reports the complete next string value; never a DOM event. */\n onValueChange: (value: string) => void\n disabled?: boolean\n 'aria-invalid'?: boolean\n 'aria-describedby'?: string\n}\nexport interface EditorTextInputProps extends EditorInputProps {\n type: 'text' | 'search'\n}\nexport interface EditorTextAreaProps extends EditorInputProps {\n /** Visible rows when supported by the control; defaults to six. */\n rows?: number\n}\nexport interface EditorMessageRowProps {\n children: ReactNode\n selected: boolean\n /** Activates this row without changing controlled selection itself. */\n onSelect: () => void\n}\nexport interface EditorPanelProps {\n children: ReactNode\n label: string\n kind: 'source' | 'translation'\n}\nexport interface EditorLayoutProps {\n toolbar: ReactNode\n navigation: ReactNode\n content: ReactNode\n}\n/** Define adapters outside render so controls retain focus across edits. */\nexport interface EditorComponents {\n Button: ComponentType<EditorButtonProps>\n TextInput: ComponentType<EditorTextInputProps>\n TextArea: ComponentType<EditorTextAreaProps>\n MessageRow: ComponentType<EditorMessageRowProps>\n Panel: ComponentType<EditorPanelProps>\n Layout: ComponentType<EditorLayoutProps>\n}\nexport interface EditorLabels {\n search: string\n messages: string\n source: string\n noMessages: string\n noSelection: string\n loading: string\n copySource: string\n reset: string\n save: string\n saving: string\n saved: string\n unsaved: string\n unchanged: string\n validation: Record<TranslationValidationError, string>\n}\nconst defaultLabels: EditorLabels = {\n search: 'Search messages',\n messages: 'Messages',\n source: 'Source message',\n noMessages: 'No matching messages',\n noSelection: 'Select a message',\n loading: 'Loading messages…',\n copySource: 'Copy source',\n reset: 'Reset',\n save: 'Save translation',\n saving: 'Saving…',\n saved: 'Translation saved.',\n unsaved: 'Unsaved changes',\n unchanged: 'No unsaved changes',\n validation: {\n empty: 'Enter a translation before saving.',\n 'invalid-source': 'The source contains invalid ICU syntax.',\n 'invalid-translation': 'The translation contains invalid ICU syntax.',\n structure:\n 'Preserve ICU arguments, tags, formatting styles, and selector branches.',\n },\n}\nexport type EditorLabelOverrides = Partial<Omit<EditorLabels, 'validation'>> & {\n validation?: Partial<EditorLabels['validation']>\n}\nfunction resolveLabels(labels?: EditorLabelOverrides): EditorLabels {\n return {\n ...defaultLabels,\n ...labels,\n validation: {...defaultLabels.validation, ...labels?.validation},\n }\n}\n/** Unstyled native controls; no CSS, icons, or localization provider is required. */\nexport const nativeEditorComponents: EditorComponents = {\n Button: ({children, onPress, disabled}) => (\n <button type=\"button\" disabled={disabled} onClick={() => onPress()}>\n {children}\n </button>\n ),\n TextInput: ({onValueChange, ...props}) => (\n <input {...props} onChange={event => onValueChange(event.target.value)} />\n ),\n TextArea: ({onValueChange, rows = 6, ...props}) => (\n <textarea\n {...props}\n rows={rows}\n onChange={event => onValueChange(event.target.value)}\n />\n ),\n MessageRow: ({children, selected, onSelect}) => (\n <button\n type=\"button\"\n aria-current={selected ? 'true' : undefined}\n onClick={() => onSelect()}\n >\n {children}\n </button>\n ),\n Panel: ({children, label}) => (\n <section aria-label={label}>{children}</section>\n ),\n Layout: ({toolbar, navigation, content}) => (\n <div>\n {toolbar}\n <div>\n {navigation}\n {content}\n </div>\n </div>\n ),\n}\nconst EditorDesignSystemContext = createContext<Readonly<EditorComponents>>(\n nativeEditorComponents\n)\n\nexport interface EditorDesignSystemProviderProps {\n /** Overrides inherit unspecified components from the nearest provider. */\n components: Partial<EditorComponents>\n children: ReactNode\n}\n/** Configure a tree once; sibling providers remain independent. */\nexport function EditorDesignSystemProvider({\n components,\n children,\n}: EditorDesignSystemProviderProps): ReactNode {\n const parent = useEditorDesignSystem()\n const value = useMemo(\n () => ({...parent, ...components}),\n [parent, components]\n )\n return (\n <EditorDesignSystemContext value={value}>\n {children}\n </EditorDesignSystemContext>\n )\n}\n/** Read the resolved controls, including native defaults outside a provider. */\nexport function useEditorDesignSystem(): Readonly<EditorComponents> {\n return useContext(EditorDesignSystemContext)\n}\ninterface ViewOptions {\n labels?: EditorLabelOverrides\n}\nexport type EditorViewMessage = Pick<\n EditorMessage,\n 'id' | 'defaultMessage' | 'description'\n>\nexport interface EditorSearch {\n value: string\n onValueChange: (value: string) => void\n}\nexport interface MessageListProps extends ViewOptions {\n messages: readonly EditorViewMessage[]\n selectedId?: string\n onSelect: (id: string) => void\n search?: EditorSearch\n loading?: boolean\n pagination?: ReactNode\n}\n/** Controlled list: it never filters, paginates, fetches, or changes selection itself. */\nexport function MessageList({\n messages,\n selectedId,\n onSelect,\n search,\n loading = false,\n pagination,\n labels,\n}: MessageListProps): ReactNode {\n const {TextInput, MessageRow} = useEditorDesignSystem()\n const text = resolveLabels(labels)\n const searchId = useId()\n return (\n <nav aria-label={text.messages} aria-busy={loading}>\n {search && (\n <div>\n <label htmlFor={searchId}>{text.search}</label>\n <TextInput\n id={searchId}\n type=\"search\"\n value={search.value}\n onValueChange={search.onValueChange}\n />\n </div>\n )}\n {loading && (\n <p>\n <output>{text.loading}</output>\n </p>\n )}\n <ul>\n {messages.map(message => (\n <li key={message.id}>\n <MessageRow\n selected={message.id === selectedId}\n onSelect={() => onSelect(message.id)}\n >\n <span>{message.defaultMessage}</span> <code>{message.id}</code>\n </MessageRow>\n </li>\n ))}\n </ul>\n {!loading && messages.length === 0 && (\n <p>\n <output>{text.noMessages}</output>\n </p>\n )}\n {pagination}\n </nav>\n )\n}\nexport interface SourceMessageProps extends ViewOptions {\n message: EditorViewMessage\n preview?: ReactNode\n context?: ReactNode\n}\nexport function SourceMessage({\n message,\n preview,\n context,\n labels,\n}: SourceMessageProps): ReactNode {\n const {Panel} = useEditorDesignSystem()\n const text = resolveLabels(labels)\n return (\n <Panel kind=\"source\" label={text.source}>\n <h2>{text.source}</h2>\n <code>{message.id}</code>\n {preview ?? <pre>{message.defaultMessage}</pre>}\n {message.description && <p>{message.description}</p>}\n {context}\n </Panel>\n )\n}\nexport type TranslationFieldDraft = Pick<\n TranslationDraftState,\n | 'value'\n | 'validationError'\n | 'changed'\n | 'isSaving'\n | 'saveError'\n | 'saved'\n | 'setTranslation'\n | 'reset'\n>\nexport interface TranslationFieldProps extends ViewOptions {\n locale: string\n /** Human-readable label; defaults to the locale identifier. */\n label?: string\n source: string\n draft: TranslationFieldDraft\n /** The caller owns confirmation, context, persistence, and receipt presentation. */\n onSave?: () => void\n /** Overrides the default copy/reset/save actions, including with null. */\n actions?: ReactNode\n preview?: ReactNode\n}\nexport function TranslationField({\n locale,\n label = locale,\n source,\n draft,\n onSave,\n actions,\n preview,\n labels,\n}: TranslationFieldProps): ReactNode {\n const {Panel, TextArea, Button} = useEditorDesignSystem()\n const text = resolveLabels(labels)\n const id = useId()\n const errorId = `${id}-error`\n const statusId = `${id}-status`\n const validation = draft.validationError\n ? text.validation[draft.validationError]\n : null\n const error = validation ?? draft.saveError?.message\n return (\n <Panel kind=\"translation\" label={label}>\n <label htmlFor={id}>{label}</label>\n <TextArea\n id={id}\n value={draft.value}\n onValueChange={draft.setTranslation}\n aria-invalid={!!validation}\n aria-describedby={error ? `${errorId} ${statusId}` : statusId}\n />\n {error && (\n <p id={errorId} role=\"alert\">\n {error}\n </p>\n )}\n <p>\n <output id={statusId}>\n {draft.isSaving\n ? text.saving\n : draft.saved\n ? text.saved\n : draft.changed\n ? text.unsaved\n : text.unchanged}\n </output>\n </p>\n {preview}\n {actions !== undefined ? (\n actions\n ) : (\n <div>\n <Button\n variant=\"secondary\"\n disabled={draft.isSaving}\n onPress={() => draft.setTranslation(source)}\n >\n {text.copySource}\n </Button>\n <Button\n variant=\"secondary\"\n disabled={!draft.changed || draft.isSaving}\n onPress={draft.reset}\n >\n {text.reset}\n </Button>\n {onSave && (\n <Button\n variant=\"primary\"\n disabled={\n !draft.changed || !!draft.validationError || draft.isSaving\n }\n onPress={onSave}\n >\n {draft.isSaving ? text.saving : text.save}\n </Button>\n )}\n </div>\n )}\n </Panel>\n )\n}\nexport type EditorTranslation = Omit<TranslationFieldProps, 'source' | 'labels'>\nexport interface TranslationEditorViewProps extends Omit<\n MessageListProps,\n 'selectedId'\n> {\n /** May be outside the loaded list, e.g. during a server-side page change. */\n selectedMessage?: EditorViewMessage\n translations: readonly EditorTranslation[]\n filters?: ReactNode\n context?: ReactNode\n sourcePreview?: ReactNode\n notice?: ReactNode\n}\n/** A stateless composition over caller-owned navigation and locale drafts. */\nexport function TranslationEditorView({\n selectedMessage,\n translations,\n filters,\n context,\n sourcePreview,\n notice,\n labels,\n ...list\n}: TranslationEditorViewProps): ReactNode {\n const {Layout} = useEditorDesignSystem()\n const text = resolveLabels(labels)\n return (\n <Layout\n toolbar={filters}\n navigation={\n <MessageList\n {...list}\n selectedId={selectedMessage?.id}\n labels={labels}\n />\n }\n content={\n <>\n {notice}\n {selectedMessage ? (\n <>\n <SourceMessage\n message={selectedMessage}\n preview={sourcePreview}\n context={context}\n labels={labels}\n />\n {translations.map(translation => (\n <TranslationField\n {...translation}\n key={`${selectedMessage.id}:${translation.locale}`}\n source={selectedMessage.defaultMessage}\n labels={labels}\n />\n ))}\n </>\n ) : (\n <p>\n <output>{text.noSelection}</output>\n </p>\n )}\n </>\n }\n />\n )\n}\n"],"mappings":";;;AA8EA,MAAM,gBAA8B;CAClC,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,YAAY;CACZ,aAAa;CACb,SAAS;CACT,YAAY;CACZ,OAAO;CACP,MAAM;CACN,QAAQ;CACR,OAAO;CACP,SAAS;CACT,WAAW;CACX,YAAY;EACV,OAAO;EACP,kBAAkB;EAClB,uBAAuB;EACvB,WACE;CACJ;AACF;AAIA,SAAS,cAAc,QAA6C;CAClE,OAAO;EACL,GAAG;EACH,GAAG;EACH,YAAY;GAAC,GAAG,cAAc;GAAY,GAAG,QAAQ;EAAU;CACjE;AACF;;AAEA,MAAa,yBAA2C;CACtD,SAAS,EAAC,UAAU,SAAS,eAC3B,oBAAC,UAAD;EAAQ,MAAK;EAAmB;EAAU,eAAe,QAAQ;EAC9D;CACK,CAAA;CAEV,YAAY,EAAC,eAAe,GAAG,YAC7B,oBAAC,SAAD;EAAO,GAAI;EAAO,WAAU,UAAS,cAAc,MAAM,OAAO,KAAK;CAAI,CAAA;CAE3E,WAAW,EAAC,eAAe,OAAO,GAAG,GAAG,YACtC,oBAAC,YAAD;EACE,GAAI;EACE;EACN,WAAU,UAAS,cAAc,MAAM,OAAO,KAAK;CACpD,CAAA;CAEH,aAAa,EAAC,UAAU,UAAU,eAChC,oBAAC,UAAD;EACE,MAAK;EACL,gBAAc,WAAW,SAAS,KAAA;EAClC,eAAe,SAAS;EAEvB;CACK,CAAA;CAEV,QAAQ,EAAC,UAAU,YACjB,oBAAC,WAAD;EAAS,cAAY;EAAQ;CAAkB,CAAA;CAEjD,SAAS,EAAC,SAAS,YAAY,cAC7B,qBAAC,OAAD,EAAA,UAAA,CACG,SACD,qBAAC,OAAD,EAAA,UAAA,CACG,YACA,OACE,EAAA,CAAA,CACF,EAAA,CAAA;AAET;AACA,MAAM,4BAA4B,cAChC,sBACF;;AAQA,SAAgB,2BAA2B,EACzC,YACA,YAC6C;CAC7C,MAAM,SAAS,sBAAsB;CACrC,MAAM,QAAQ,eACL;EAAC,GAAG;EAAQ,GAAG;CAAU,IAChC,CAAC,QAAQ,UAAU,CACrB;CACA,OACE,oBAAC,2BAAD;EAAkC;EAC/B;CACwB,CAAA;AAE/B;;AAEA,SAAgB,wBAAoD;CAClE,OAAO,WAAW,yBAAyB;AAC7C;;AAqBA,SAAgB,YAAY,EAC1B,UACA,YACA,UACA,QACA,UAAU,OACV,YACA,UAC8B;CAC9B,MAAM,EAAC,WAAW,eAAc,sBAAsB;CACtD,MAAM,OAAO,cAAc,MAAM;CACjC,MAAM,WAAW,MAAM;CACvB,OACE,qBAAC,OAAD;EAAK,cAAY,KAAK;EAAU,aAAW;EAA3C,UAAA;GACG,UACC,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,SAAD;IAAO,SAAS;IAAW,UAAA,KAAK;GAAc,CAAA,GAC9C,oBAAC,WAAD;IACE,IAAI;IACJ,MAAK;IACL,OAAO,OAAO;IACd,eAAe,OAAO;GACvB,CAAA,CACE,EAAA,CAAA;GAEN,WACC,oBAAC,KAAD,EAAA,UACE,oBAAC,UAAD,EAAA,UAAS,KAAK,QAAgB,CAAA,EAC7B,CAAA;GAEL,oBAAC,MAAD,EAAA,UACG,SAAS,KAAI,YACZ,oBAAC,MAAD,EAAA,UACE,qBAAC,YAAD;IACE,UAAU,QAAQ,OAAO;IACzB,gBAAgB,SAAS,QAAQ,EAAE;IAFrC,UAAA;KAIE,oBAAC,QAAD,EAAA,UAAO,QAAQ,eAAqB,CAAA;KAAC;KAAC,oBAAC,QAAD,EAAA,UAAO,QAAQ,GAAS,CAAA;IACpD;GACV,CAAA,EAAA,GAPK,QAAQ,EAOb,CACL,EACC,CAAA;GACH,CAAC,WAAW,SAAS,WAAW,KAC/B,oBAAC,KAAD,EAAA,UACE,oBAAC,UAAD,EAAA,UAAS,KAAK,WAAmB,CAAA,EAChC,CAAA;GAEJ;EACE;;AAET;AAMA,SAAgB,cAAc,EAC5B,SACA,SACA,SACA,UACgC;CAChC,MAAM,EAAC,UAAS,sBAAsB;CACtC,MAAM,OAAO,cAAc,MAAM;CACjC,OACE,qBAAC,OAAD;EAAO,MAAK;EAAS,OAAO,KAAK;EAAjC,UAAA;GACE,oBAAC,MAAD,EAAA,UAAK,KAAK,OAAW,CAAA;GACrB,oBAAC,QAAD,EAAA,UAAO,QAAQ,GAAS,CAAA;GACvB,WAAW,oBAAC,OAAD,EAAA,UAAM,QAAQ,eAAoB,CAAA;GAC7C,QAAQ,eAAe,oBAAC,KAAD,EAAA,UAAI,QAAQ,YAAe,CAAA;GAClD;EACI;;AAEX;AAwBA,SAAgB,iBAAiB,EAC/B,QACA,QAAQ,QACR,QACA,OACA,QACA,SACA,SACA,UACmC;CACnC,MAAM,EAAC,OAAO,UAAU,WAAU,sBAAsB;CACxD,MAAM,OAAO,cAAc,MAAM;CACjC,MAAM,KAAK,MAAM;CACjB,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,WAAW,GAAG,GAAG;CACvB,MAAM,aAAa,MAAM,kBACrB,KAAK,WAAW,MAAM,mBACtB;CACJ,MAAM,QAAQ,cAAc,MAAM,WAAW;CAC7C,OACE,qBAAC,OAAD;EAAO,MAAK;EAAqB;EAAjC,UAAA;GACE,oBAAC,SAAD;IAAO,SAAS;IAAK,UAAA;GAAa,CAAA;GAClC,oBAAC,UAAD;IACM;IACJ,OAAO,MAAM;IACb,eAAe,MAAM;IACrB,gBAAc,CAAC,CAAC;IAChB,oBAAkB,QAAQ,GAAG,QAAQ,GAAG,aAAa;GACtD,CAAA;GACA,SACC,oBAAC,KAAD;IAAG,IAAI;IAAS,MAAK;IAClB,UAAA;GACA,CAAA;GAEL,oBAAC,KAAD,EAAA,UACE,oBAAC,UAAD;IAAQ,IAAI;IACT,UAAA,MAAM,WACH,KAAK,SACL,MAAM,QACJ,KAAK,QACL,MAAM,UACJ,KAAK,UACL,KAAK;GACP,CAAA,EACP,CAAA;GACF;GACA,YAAY,KAAA,IACX,UAEA,qBAAC,OAAD,EAAA,UAAA;IACE,oBAAC,QAAD;KACE,SAAQ;KACR,UAAU,MAAM;KAChB,eAAe,MAAM,eAAe,MAAM;KAEzC,UAAA,KAAK;IACA,CAAA;IACR,oBAAC,QAAD;KACE,SAAQ;KACR,UAAU,CAAC,MAAM,WAAW,MAAM;KAClC,SAAS,MAAM;KAEd,UAAA,KAAK;IACA,CAAA;IACP,UACC,oBAAC,QAAD;KACE,SAAQ;KACR,UACE,CAAC,MAAM,WAAW,CAAC,CAAC,MAAM,mBAAmB,MAAM;KAErD,SAAS;KAER,UAAA,MAAM,WAAW,KAAK,SAAS,KAAK;IAC/B,CAAA;GAEP,EAAA,CAAA;EAEF;;AAEX;;AAeA,SAAgB,sBAAsB,EACpC,iBACA,cACA,SACA,SACA,eACA,QACA,QACA,GAAG,QACqC;CACxC,MAAM,EAAC,WAAU,sBAAsB;CACvC,MAAM,OAAO,cAAc,MAAM;CACjC,OACE,oBAAC,QAAD;EACE,SAAS;EACT,YACE,oBAAC,aAAD;GACE,GAAI;GACJ,YAAY,iBAAiB;GACrB;EACT,CAAA;EAEH,SACE,qBAAA,UAAA,EAAA,UAAA,CACG,QACA,kBACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,eAAD;GACE,SAAS;GACT,SAAS;GACA;GACD;EACT,CAAA,GACA,aAAa,KAAI,gBAChB,8BAAC,kBAAD;GACE,GAAI;GACJ,KAAK,GAAG,gBAAgB,GAAG,GAAG,YAAY;GAC1C,QAAQ,gBAAgB;GAChB;EACT,CAAA,CACF,CACD,EAAA,CAAA,IAEF,oBAAC,KAAD,EAAA,UACE,oBAAC,UAAD,EAAA,UAAS,KAAK,YAAoB,CAAA,EACjC,CAAA,CAEL,EAAA,CAAA;CAEL,CAAA;AAEL"}
|
package/header.d.ts
DELETED
package/header.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../../../packages/editor/header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,WAAW,KAAK;CAAG;AAEzB,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAgB3B,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/header.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var tslib_1 = require("tslib");
|
|
4
|
-
var react_1 = (0, tslib_1.__importDefault)(require("react"));
|
|
5
|
-
var core_1 = require("@material-ui/core");
|
|
6
|
-
function handleClick(event) {
|
|
7
|
-
event.preventDefault();
|
|
8
|
-
console.info('You clicked a breadcrumb.');
|
|
9
|
-
}
|
|
10
|
-
var Header = function (_) {
|
|
11
|
-
return (react_1.default.createElement(core_1.Breadcrumbs, { "aria-label": "breadcrumb" },
|
|
12
|
-
react_1.default.createElement(core_1.Link, { color: "inherit", href: "/", onClick: handleClick }, "Material-UI"),
|
|
13
|
-
react_1.default.createElement(core_1.Link, { color: "inherit", href: "/getting-started/installation/", onClick: handleClick }, "Core"),
|
|
14
|
-
react_1.default.createElement(core_1.Typography, { color: "textPrimary" }, "Breadcrumb")));
|
|
15
|
-
};
|
|
16
|
-
exports.default = Header;
|
package/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/editor/index.tsx"],"names":[],"mappings":";AAyCA,wBAAgB,OAAO,gBAoItB;AAED,MAAM,CAAC,OAAO,UAAU,GAAG,gBAmB1B"}
|
package/lib/header.d.ts
DELETED
package/lib/header.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../../../../packages/editor/header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,WAAW,KAAK;CAAG;AAEzB,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAgB3B,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/lib/header.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Typography, Breadcrumbs, Link } from '@material-ui/core';
|
|
3
|
-
function handleClick(event) {
|
|
4
|
-
event.preventDefault();
|
|
5
|
-
console.info('You clicked a breadcrumb.');
|
|
6
|
-
}
|
|
7
|
-
var Header = function (_) {
|
|
8
|
-
return (React.createElement(Breadcrumbs, { "aria-label": "breadcrumb" },
|
|
9
|
-
React.createElement(Link, { color: "inherit", href: "/", onClick: handleClick }, "Material-UI"),
|
|
10
|
-
React.createElement(Link, { color: "inherit", href: "/getting-started/installation/", onClick: handleClick }, "Core"),
|
|
11
|
-
React.createElement(Typography, { color: "textPrimary" }, "Breadcrumb")));
|
|
12
|
-
};
|
|
13
|
-
export default Header;
|
package/lib/index.d.ts
DELETED
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/editor/index.tsx"],"names":[],"mappings":";AAyCA,wBAAgB,OAAO,gBAoItB;AAED,MAAM,CAAC,OAAO,UAAU,GAAG,gBAmB1B"}
|
package/lib/index.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { __awaiter, __generator } from "tslib";
|
|
2
|
-
import React, { useEffect, useState } from 'react';
|
|
3
|
-
import { useMediaQuery, createMuiTheme, ThemeProvider, CssBaseline, Grid, TextField, AppBar, Toolbar, Box, Typography, ButtonGroup, Button, Tabs, Tab, IconButton, Drawer, List, ListItem, ListItemText, } from '@material-ui/core';
|
|
4
|
-
import { Menu, AddAlert, NotificationsOff } from '@material-ui/icons';
|
|
5
|
-
import Header from './header';
|
|
6
|
-
import { IntlProvider, useIntl } from 'react-intl';
|
|
7
|
-
import Messages from './messages';
|
|
8
|
-
var MESSAGES_COUNT = 50;
|
|
9
|
-
function fetchData() {
|
|
10
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
11
|
-
var en, ru;
|
|
12
|
-
return __generator(this, function (_a) {
|
|
13
|
-
switch (_a.label) {
|
|
14
|
-
case 0: return [4 /*yield*/, fetch('/fixtures/en.json')];
|
|
15
|
-
case 1: return [4 /*yield*/, (_a.sent()).json()];
|
|
16
|
-
case 2:
|
|
17
|
-
en = _a.sent();
|
|
18
|
-
return [4 /*yield*/, fetch('/fixtures/ru.json')];
|
|
19
|
-
case 3: return [4 /*yield*/, (_a.sent()).json()];
|
|
20
|
-
case 4:
|
|
21
|
-
ru = _a.sent();
|
|
22
|
-
return [2 /*return*/, Object.keys(en)
|
|
23
|
-
.slice(MESSAGES_COUNT)
|
|
24
|
-
.map(function (id) { return ({
|
|
25
|
-
id: id,
|
|
26
|
-
defaultMessage: en[id],
|
|
27
|
-
translatedMessage: ru[id],
|
|
28
|
-
}); })];
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
export function CoreApp() {
|
|
34
|
-
var intl = useIntl();
|
|
35
|
-
var _a = useState([]), messages = _a[0], setMessages = _a[1];
|
|
36
|
-
var _b = useState(true), isLoading = _b[0], setIsLoading = _b[1];
|
|
37
|
-
useEffect(function () {
|
|
38
|
-
;
|
|
39
|
-
(function () {
|
|
40
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
41
|
-
var _a;
|
|
42
|
-
return __generator(this, function (_b) {
|
|
43
|
-
switch (_b.label) {
|
|
44
|
-
case 0:
|
|
45
|
-
_a = setMessages;
|
|
46
|
-
return [4 /*yield*/, fetchData()];
|
|
47
|
-
case 1:
|
|
48
|
-
_a.apply(void 0, [_b.sent()]);
|
|
49
|
-
setIsLoading(false);
|
|
50
|
-
return [2 /*return*/];
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
})();
|
|
55
|
-
}, []);
|
|
56
|
-
return (React.createElement(React.Fragment, null,
|
|
57
|
-
React.createElement(CssBaseline, null),
|
|
58
|
-
React.createElement(Box, { height: "100vh" },
|
|
59
|
-
React.createElement(AppBar, { position: "static" },
|
|
60
|
-
React.createElement(Toolbar, { variant: "dense" },
|
|
61
|
-
React.createElement(IconButton, { edge: "start", color: "inherit", "aria-label": "menu" },
|
|
62
|
-
React.createElement(Menu, null)),
|
|
63
|
-
React.createElement(Drawer, { anchor: "left" },
|
|
64
|
-
React.createElement(List, null, ['Inbox', 'Starred', 'Send email', 'Drafts'].map(function (text) { return (React.createElement(ListItem, { button: true, key: text },
|
|
65
|
-
React.createElement(ListItemText, { primary: text }))); }))),
|
|
66
|
-
React.createElement(Header, null),
|
|
67
|
-
React.createElement(AddAlert, null),
|
|
68
|
-
React.createElement(NotificationsOff, null))),
|
|
69
|
-
React.createElement(Grid, { container: true, spacing: 0 },
|
|
70
|
-
React.createElement(Grid, { xs: 3 },
|
|
71
|
-
React.createElement("form", { noValidate: true, autoComplete: "off" },
|
|
72
|
-
React.createElement(TextField, { type: "search", fullWidth: true, margin: "none", size: "small", variant: "filled", label: intl.formatMessage({
|
|
73
|
-
id: 'search-bar-label',
|
|
74
|
-
defaultMessage: 'Search message',
|
|
75
|
-
description: 'label in search bar',
|
|
76
|
-
}) })),
|
|
77
|
-
React.createElement(Box, { borderRight: 1, overflow: "auto", height: "calc(100vh - 108px)" },
|
|
78
|
-
React.createElement(Messages, { messages: messages, isLoading: isLoading, count: MESSAGES_COUNT }))),
|
|
79
|
-
React.createElement(Grid, { xs: 6 },
|
|
80
|
-
React.createElement(Box, { borderRight: 1, overflow: "auto", height: "calc(100vh - 48px)" },
|
|
81
|
-
React.createElement(Box, { p: 2 },
|
|
82
|
-
React.createElement(Typography, { variant: "h6", component: "h6" }, "English message"),
|
|
83
|
-
React.createElement(Typography, { variant: "body2", component: "span" },
|
|
84
|
-
"Description",
|
|
85
|
-
' ',
|
|
86
|
-
React.createElement(Typography, { variant: "body2", color: "textSecondary", component: "span" }, "This is a description"))),
|
|
87
|
-
React.createElement(TextField, { multiline: true, fullWidth: true, margin: "dense", size: "small", variant: "filled", rows: 4, label: intl.formatMessage({
|
|
88
|
-
id: 'translated-box-label',
|
|
89
|
-
defaultMessage: 'Translate',
|
|
90
|
-
description: 'translated box label',
|
|
91
|
-
}) }),
|
|
92
|
-
React.createElement(Box, { px: 2, py: 1, display: "flex", justifyContent: "space-between", alignItems: "center" },
|
|
93
|
-
React.createElement(Typography, { variant: "body2", component: "span" }, "71 / 101"),
|
|
94
|
-
React.createElement(Box, null,
|
|
95
|
-
React.createElement(ButtonGroup, { variant: "text", color: "primary", "aria-label": "text primary button group" },
|
|
96
|
-
React.createElement(Button, null, "Copy"),
|
|
97
|
-
React.createElement(Button, null, "Clear")),
|
|
98
|
-
React.createElement(Button, { variant: "contained", color: "primary" }, "Translate"))))),
|
|
99
|
-
React.createElement(Grid, { xs: 3 },
|
|
100
|
-
React.createElement(Tabs, { indicatorColor: "primary", textColor: "primary", centered: true, "aria-label": "disabled tabs example", value: 0, variant: "fullWidth" },
|
|
101
|
-
React.createElement(Tab, { label: "Active" }),
|
|
102
|
-
React.createElement(Tab, { label: "Active" })))))));
|
|
103
|
-
}
|
|
104
|
-
export default function App() {
|
|
105
|
-
var prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
|
106
|
-
var theme = React.useMemo(function () {
|
|
107
|
-
return createMuiTheme({
|
|
108
|
-
palette: {
|
|
109
|
-
type: prefersDarkMode ? 'dark' : 'light',
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
}, [prefersDarkMode]);
|
|
113
|
-
return (React.createElement(IntlProvider, { locale: "en", messages: {} },
|
|
114
|
-
React.createElement(ThemeProvider, { theme: theme },
|
|
115
|
-
React.createElement(CoreApp, null))));
|
|
116
|
-
}
|
package/lib/main.d.ts
DELETED
package/lib/main.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../../packages/editor/main.tsx"],"names":[],"mappings":""}
|
package/lib/main.js
DELETED
package/lib/message.d.ts
DELETED
package/lib/message.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../../../packages/editor/message.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAezB,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAuFD,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAG5B,CAAA;AAED,eAAe,OAAO,CAAA"}
|