svelte-intlayer 7.1.8 → 7.1.9
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/dist/IntlayerNodeWrapper.svelte +10 -0
- package/dist/IntlayerNodeWrapper.svelte.d.ts +22 -0
- package/dist/client/IntlayerProvider.svelte +24 -0
- package/dist/client/IntlayerProvider.svelte.d.ts +30 -0
- package/dist/{types/client → client}/getBrowserLocale.d.ts +1 -1
- package/dist/client/getBrowserLocale.js +17 -0
- package/dist/client/index.js +12 -0
- package/dist/{types/client → client}/intlayerContext.d.ts +1 -1
- package/dist/client/intlayerContext.js +8 -0
- package/dist/client/intlayerStore.d.ts +11 -0
- package/dist/client/intlayerStore.js +19 -0
- package/dist/{types/client → client}/useDictionary.d.ts +3 -3
- package/dist/client/useDictionary.js +18 -0
- package/dist/{types/client → client}/useDictionaryAsync.d.ts +2 -2
- package/dist/client/useDictionaryAsync.js +38 -0
- package/dist/{types/client → client}/useDictionaryDynamic.d.ts +2 -2
- package/dist/client/useDictionaryDynamic.js +38 -0
- package/dist/{types/client → client}/useIntlayer.d.ts +3 -3
- package/dist/client/useIntlayer.js +18 -0
- package/dist/{types/client → client}/useLocale.d.ts +4 -4
- package/dist/client/useLocale.js +33 -0
- package/dist/client/useLocaleStorage.d.ts +39 -0
- package/dist/client/useLocaleStorage.js +52 -0
- package/dist/editor/ContentSelector.svelte +125 -0
- package/dist/editor/ContentSelector.svelte.d.ts +35 -0
- package/dist/editor/ContentSelectorWrapper.svelte +69 -0
- package/dist/editor/ContentSelectorWrapper.svelte.d.ts +31 -0
- package/dist/{types/editor → editor}/communicator.d.ts +1 -1
- package/dist/editor/communicator.js +54 -0
- package/dist/{types/editor → editor}/dictionariesRecord.d.ts +2 -2
- package/dist/editor/dictionariesRecord.js +16 -0
- package/dist/{types/editor → editor}/editorEnabled.d.ts +1 -1
- package/dist/editor/editorEnabled.js +41 -0
- package/dist/{types/editor → editor}/focusDictionary.d.ts +2 -2
- package/dist/editor/focusDictionary.js +22 -0
- package/dist/editor/index.js +9 -0
- package/dist/{types/editor → editor}/useCrossFrameMessageListener.d.ts +1 -1
- package/dist/editor/useCrossFrameMessageListener.js +65 -0
- package/dist/{types/editor → editor}/useCrossFrameState.d.ts +2 -2
- package/dist/editor/useCrossFrameState.js +82 -0
- package/dist/editor/useEditor.js +46 -0
- package/dist/editor/useIframeClickInterceptor.js +29 -0
- package/dist/{types/getDictionary.d.ts → getDictionary.d.ts} +3 -3
- package/dist/getDictionary.js +18 -0
- package/dist/{types/getIntlayer.d.ts → getIntlayer.d.ts} +3 -3
- package/dist/getIntlayer.js +18 -0
- package/dist/{types/index.d.ts → index.d.ts} +3 -3
- package/dist/index.js +7 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +6 -0
- package/dist/markdown/MarkdownMetadataRenderer.svelte +21 -0
- package/dist/markdown/MarkdownMetadataRenderer.svelte.d.ts +25 -0
- package/dist/markdown/MarkdownMetadataWithSelector.svelte +21 -0
- package/dist/markdown/MarkdownMetadataWithSelector.svelte.d.ts +24 -0
- package/dist/markdown/MarkdownProvider.svelte +9 -0
- package/dist/markdown/MarkdownProvider.svelte.d.ts +29 -0
- package/dist/markdown/MarkdownRenderer.svelte +11 -0
- package/dist/markdown/MarkdownRenderer.svelte.d.ts +20 -0
- package/dist/markdown/MarkdownWithSelector.svelte +15 -0
- package/dist/markdown/MarkdownWithSelector.svelte.d.ts +23 -0
- package/dist/markdown/context.js +10 -0
- package/dist/markdown/index.js +4 -0
- package/dist/{types/plugins.d.ts → plugins.d.ts} +3 -3
- package/dist/plugins.js +87 -0
- package/dist/renderIntlayerNode.js +44 -0
- package/dist/setIntlayerMarkdown.d.ts +1 -0
- package/dist/setIntlayerMarkdown.js +2 -0
- package/package.json +22 -30
- package/dist/ContentSelectorWrapper-Ct4vOl_g.js +0 -163
- package/dist/ContentSelectorWrapper-DMEqv3vE.cjs +0 -10
- package/dist/MarkdownRenderer-BFrmuaFN.js +0 -47
- package/dist/MarkdownRenderer-DyK7SeHa.cjs +0 -1
- package/dist/cjs/client/getBrowserLocale.cjs +0 -1
- package/dist/cjs/client/index.cjs +0 -1
- package/dist/cjs/client/intlayerContext.cjs +0 -1
- package/dist/cjs/client/intlayerStore.cjs +0 -1
- package/dist/cjs/client/useDictionary.cjs +0 -1
- package/dist/cjs/client/useDictionaryAsync.cjs +0 -1
- package/dist/cjs/client/useDictionaryDynamic.cjs +0 -1
- package/dist/cjs/client/useIntlayer.cjs +0 -1
- package/dist/cjs/client/useLocale.cjs +0 -1
- package/dist/cjs/client/useLocaleStorage.cjs +0 -1
- package/dist/cjs/editor/communicator.cjs +0 -1
- package/dist/cjs/editor/dictionariesRecord.cjs +0 -1
- package/dist/cjs/editor/editorEnabled.cjs +0 -1
- package/dist/cjs/editor/focusDictionary.cjs +0 -1
- package/dist/cjs/editor/index.cjs +0 -1
- package/dist/cjs/editor/useCrossFrameMessageListener.cjs +0 -1
- package/dist/cjs/editor/useCrossFrameState.cjs +0 -1
- package/dist/cjs/editor/useEditor.cjs +0 -1
- package/dist/cjs/editor/useIframeClickInterceptor.cjs +0 -1
- package/dist/cjs/getDictionary.cjs +0 -1
- package/dist/cjs/getIntlayer.cjs +0 -1
- package/dist/cjs/index.cjs +0 -1
- package/dist/cjs/markdown/context.cjs +0 -1
- package/dist/cjs/markdown/index.cjs +0 -1
- package/dist/cjs/plugins.cjs +0 -1
- package/dist/cjs/renderIntlayerNode.cjs +0 -1
- package/dist/cjs/setIntlayerMarkdown.cjs +0 -1
- package/dist/esm/client/getBrowserLocale.mjs +0 -9
- package/dist/esm/client/index.mjs +0 -19
- package/dist/esm/client/intlayerContext.mjs +0 -8
- package/dist/esm/client/intlayerStore.mjs +0 -16
- package/dist/esm/client/useDictionary.mjs +0 -14
- package/dist/esm/client/useDictionaryAsync.mjs +0 -27
- package/dist/esm/client/useDictionaryDynamic.mjs +0 -27
- package/dist/esm/client/useIntlayer.mjs +0 -14
- package/dist/esm/client/useLocale.mjs +0 -33
- package/dist/esm/client/useLocaleStorage.mjs +0 -29
- package/dist/esm/editor/communicator.mjs +0 -31
- package/dist/esm/editor/dictionariesRecord.mjs +0 -20
- package/dist/esm/editor/editorEnabled.mjs +0 -28
- package/dist/esm/editor/focusDictionary.mjs +0 -21
- package/dist/esm/editor/index.mjs +0 -23
- package/dist/esm/editor/useCrossFrameMessageListener.mjs +0 -37
- package/dist/esm/editor/useCrossFrameState.mjs +0 -53
- package/dist/esm/editor/useEditor.mjs +0 -38
- package/dist/esm/editor/useIframeClickInterceptor.mjs +0 -26
- package/dist/esm/getDictionary.mjs +0 -18
- package/dist/esm/getIntlayer.mjs +0 -14
- package/dist/esm/index.mjs +0 -37
- package/dist/esm/markdown/context.mjs +0 -11
- package/dist/esm/markdown/index.mjs +0 -21
- package/dist/esm/plugins.mjs +0 -133
- package/dist/esm/renderIntlayerNode.mjs +0 -51
- package/dist/esm/setIntlayerMarkdown.mjs +0 -5
- package/dist/types/IntlayerNodeWrapper.svelte.d.ts +0 -1
- package/dist/types/client/intlayerStore.d.ts +0 -11
- package/dist/types/client/useLocaleStorage.d.ts +0 -39
- package/dist/types/editor/ContentSelector.svelte.d.ts +0 -1
- package/dist/types/editor/ContentSelectorWrapper.svelte.d.ts +0 -1
- package/dist/types/markdown/MarkdownMetadataRenderer.svelte.d.ts +0 -1
- package/dist/types/markdown/MarkdownMetadataWithSelector.svelte.d.ts +0 -1
- package/dist/types/markdown/MarkdownProvider.svelte.d.ts +0 -1
- package/dist/types/markdown/MarkdownRenderer.svelte.d.ts +0 -1
- package/dist/types/markdown/MarkdownWithSelector.svelte.d.ts +0 -1
- package/dist/types/setIntlayerMarkdown.d.ts +0 -1
- /package/dist/{types/client → client}/index.d.ts +0 -0
- /package/dist/{types/editor → editor}/index.d.ts +0 -0
- /package/dist/{types/editor → editor}/useEditor.d.ts +0 -0
- /package/dist/{types/editor → editor}/useIframeClickInterceptor.d.ts +0 -0
- /package/dist/{types/markdown → markdown}/context.d.ts +0 -0
- /package/dist/{types/markdown → markdown}/index.d.ts +0 -0
- /package/dist/{types/renderIntlayerNode.d.ts → renderIntlayerNode.d.ts} +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
15
|
+
default: any;
|
|
16
|
+
} ? Props extends Record<string, never> ? any : {
|
|
17
|
+
children?: any;
|
|
18
|
+
} : {});
|
|
19
|
+
declare const ContentSelector: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
20
|
+
onClickOutside?: (() => void) | undefined;
|
|
21
|
+
pressDuration?: number;
|
|
22
|
+
isSelecting?: boolean;
|
|
23
|
+
onPress?: (() => void) | undefined;
|
|
24
|
+
onUnhover?: (() => void) | undefined;
|
|
25
|
+
onHover?: (() => void) | undefined;
|
|
26
|
+
onClick?: ((event: MouseEvent) => void) | undefined;
|
|
27
|
+
}, {
|
|
28
|
+
default: {};
|
|
29
|
+
}>, {
|
|
30
|
+
[evt: string]: CustomEvent<any>;
|
|
31
|
+
}, {
|
|
32
|
+
default: {};
|
|
33
|
+
}, {}, string>;
|
|
34
|
+
type ContentSelector = InstanceType<typeof ContentSelector>;
|
|
35
|
+
export default ContentSelector;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { isSameKeyPath, type NodeProps } from '@intlayer/core';
|
|
3
|
+
import { MessageKey } from '@intlayer/editor';
|
|
4
|
+
import { NodeType } from '@intlayer/types';
|
|
5
|
+
import { get } from 'svelte/store';
|
|
6
|
+
import ContentSelector from './ContentSelector.svelte';
|
|
7
|
+
import { useCommunicator } from './communicator';
|
|
8
|
+
import { useEditorEnabled } from './editorEnabled';
|
|
9
|
+
import { useFocusDictionary } from './focusDictionary';
|
|
10
|
+
import { useEditor } from './useEditor';
|
|
11
|
+
|
|
12
|
+
export let dictionaryKey: NodeProps['dictionaryKey'];
|
|
13
|
+
export let keyPath: NodeProps['keyPath'];
|
|
14
|
+
|
|
15
|
+
const { focusedContent, setFocusedContent } = useFocusDictionary();
|
|
16
|
+
const editorEnabled = useEditorEnabled();
|
|
17
|
+
const communicatorStore = useCommunicator();
|
|
18
|
+
const { enabled } = editorEnabled;
|
|
19
|
+
|
|
20
|
+
useEditor();
|
|
21
|
+
|
|
22
|
+
$: filteredKeyPath = keyPath.filter((key) => key.type !== NodeType.Translation);
|
|
23
|
+
|
|
24
|
+
$: isSelected =
|
|
25
|
+
$focusedContent?.dictionaryKey === dictionaryKey &&
|
|
26
|
+
($focusedContent?.keyPath?.length ?? 0) > 0 &&
|
|
27
|
+
isSameKeyPath($focusedContent?.keyPath ?? [], filteredKeyPath);
|
|
28
|
+
|
|
29
|
+
const handleSelect = () => {
|
|
30
|
+
setFocusedContent({
|
|
31
|
+
dictionaryKey,
|
|
32
|
+
keyPath: filteredKeyPath,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleHover = () => {
|
|
37
|
+
const { postMessage, senderId } = get(communicatorStore);
|
|
38
|
+
postMessage({
|
|
39
|
+
type: `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,
|
|
40
|
+
data: {
|
|
41
|
+
dictionaryKey,
|
|
42
|
+
keyPath: filteredKeyPath,
|
|
43
|
+
},
|
|
44
|
+
senderId,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handleUnhover = () => {
|
|
49
|
+
const { postMessage, senderId } = get(communicatorStore);
|
|
50
|
+
postMessage({
|
|
51
|
+
type: `${MessageKey.INTLAYER_HOVERED_CONTENT_CHANGED}/post`,
|
|
52
|
+
data: null,
|
|
53
|
+
senderId,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
{#if $enabled}
|
|
59
|
+
<ContentSelector
|
|
60
|
+
onPress={handleSelect}
|
|
61
|
+
isSelecting={isSelected}
|
|
62
|
+
onHover={handleHover}
|
|
63
|
+
onUnhover={handleUnhover}
|
|
64
|
+
>
|
|
65
|
+
<slot />
|
|
66
|
+
</ContentSelector>
|
|
67
|
+
{:else}
|
|
68
|
+
<slot />
|
|
69
|
+
{/if}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type NodeProps } from '@intlayer/core';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
16
|
+
default: any;
|
|
17
|
+
} ? Props extends Record<string, never> ? any : {
|
|
18
|
+
children?: any;
|
|
19
|
+
} : {});
|
|
20
|
+
declare const ContentSelectorWrapper: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
21
|
+
dictionaryKey: NodeProps["dictionaryKey"];
|
|
22
|
+
keyPath: NodeProps["keyPath"];
|
|
23
|
+
}, {
|
|
24
|
+
default: {};
|
|
25
|
+
}>, {
|
|
26
|
+
[evt: string]: CustomEvent<any>;
|
|
27
|
+
}, {
|
|
28
|
+
default: {};
|
|
29
|
+
}, {}, string>;
|
|
30
|
+
type ContentSelectorWrapper = InstanceType<typeof ContentSelectorWrapper>;
|
|
31
|
+
export default ContentSelectorWrapper;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import configuration from '@intlayer/config/built';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { writable } from 'svelte/store';
|
|
4
|
+
const randomUUID = () => Math.random().toString(36).slice(2);
|
|
5
|
+
const { editor } = configuration;
|
|
6
|
+
const postMessage = (data) => {
|
|
7
|
+
if (typeof window === 'undefined')
|
|
8
|
+
return;
|
|
9
|
+
const isInIframe = window.self !== window.top;
|
|
10
|
+
if (!isInIframe)
|
|
11
|
+
return;
|
|
12
|
+
if (editor.applicationURL.length > 0) {
|
|
13
|
+
window.postMessage(data, editor.applicationURL);
|
|
14
|
+
}
|
|
15
|
+
if (editor.editorURL.length > 0) {
|
|
16
|
+
window.parent.postMessage(data, editor.editorURL);
|
|
17
|
+
}
|
|
18
|
+
if (editor.cmsURL.length > 0) {
|
|
19
|
+
window.parent.postMessage(data, editor.cmsURL);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const defaultValue = {
|
|
23
|
+
postMessage,
|
|
24
|
+
allowedOrigins: [
|
|
25
|
+
editor?.applicationURL,
|
|
26
|
+
editor?.editorURL,
|
|
27
|
+
editor?.cmsURL,
|
|
28
|
+
],
|
|
29
|
+
senderId: randomUUID(),
|
|
30
|
+
};
|
|
31
|
+
const COMMUNICATOR_KEY = Symbol('INTLAYER_COMMUNICATOR');
|
|
32
|
+
export const createCommunicator = (options = {}) => {
|
|
33
|
+
const store = writable({
|
|
34
|
+
...defaultValue,
|
|
35
|
+
...options,
|
|
36
|
+
});
|
|
37
|
+
setContext(COMMUNICATOR_KEY, store);
|
|
38
|
+
return store;
|
|
39
|
+
};
|
|
40
|
+
export const useCommunicator = () => {
|
|
41
|
+
let context;
|
|
42
|
+
// `getContext` must only run inside a component.
|
|
43
|
+
// If this is called in plain JS, we catch the error and fallback.
|
|
44
|
+
try {
|
|
45
|
+
context = getContext(COMMUNICATOR_KEY);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// called outside component -> ignore, we’ll use global store
|
|
49
|
+
}
|
|
50
|
+
if (!context) {
|
|
51
|
+
return createCommunicator();
|
|
52
|
+
}
|
|
53
|
+
return context;
|
|
54
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Dictionary, LocalDictionaryId } from '@intlayer/types';
|
|
1
|
+
import type { Dictionary, LocalDictionaryId } from '@intlayer/types';
|
|
2
2
|
export type DictionaryContent = Record<LocalDictionaryId, Dictionary>;
|
|
3
3
|
export declare const useDictionariesRecord: () => {
|
|
4
|
-
dictionariesRecord: import(
|
|
4
|
+
dictionariesRecord: import("svelte/store").Writable<DictionaryContent | undefined>;
|
|
5
5
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MessageKey } from '@intlayer/editor';
|
|
2
|
+
import { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';
|
|
3
|
+
import { useCrossFrameState } from './useCrossFrameState';
|
|
4
|
+
let loaded = false;
|
|
5
|
+
export const useDictionariesRecord = () => {
|
|
6
|
+
const [dictionariesRecord, setDictionariesRecord] = useCrossFrameState(MessageKey.INTLAYER_LOCALE_DICTIONARIES_CHANGED, {});
|
|
7
|
+
if (!loaded && typeof window !== 'undefined') {
|
|
8
|
+
const unmergedDictionaries = getUnmergedDictionaries();
|
|
9
|
+
const dictionariesList = Object.fromEntries(Object.values(unmergedDictionaries)
|
|
10
|
+
.flat()
|
|
11
|
+
.map((dictionary) => [dictionary.localId, dictionary]));
|
|
12
|
+
setDictionariesRecord(dictionariesList);
|
|
13
|
+
loaded = true;
|
|
14
|
+
}
|
|
15
|
+
return { dictionariesRecord };
|
|
16
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import configuration from '@intlayer/config/built';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { derived, writable } from 'svelte/store';
|
|
4
|
+
const EDITOR_ENABLED_KEY = Symbol('EDITOR_ENABLED');
|
|
5
|
+
const detectIframe = () => {
|
|
6
|
+
if (typeof window === 'undefined')
|
|
7
|
+
return false;
|
|
8
|
+
return window.self !== window.top;
|
|
9
|
+
};
|
|
10
|
+
export const createEditorEnabledClient = () => {
|
|
11
|
+
const settingEnabled = writable(configuration.editor.enabled);
|
|
12
|
+
const wrapperEnabled = writable(false);
|
|
13
|
+
const isInIframe = writable(false);
|
|
14
|
+
const enabled = derived([settingEnabled, wrapperEnabled, isInIframe], ([$setting, $wrapper, $iframe]) => $setting && $wrapper && $iframe);
|
|
15
|
+
if (typeof window !== 'undefined') {
|
|
16
|
+
isInIframe.set(detectIframe());
|
|
17
|
+
}
|
|
18
|
+
const state = {
|
|
19
|
+
settingEnabled,
|
|
20
|
+
wrapperEnabled,
|
|
21
|
+
isInIframe,
|
|
22
|
+
enabled,
|
|
23
|
+
};
|
|
24
|
+
setContext(EDITOR_ENABLED_KEY, state);
|
|
25
|
+
return state;
|
|
26
|
+
};
|
|
27
|
+
export const useEditorEnabled = () => {
|
|
28
|
+
let context;
|
|
29
|
+
// `getContext` must only run inside a component.
|
|
30
|
+
// If this is called in plain JS, we catch the error and fallback.
|
|
31
|
+
try {
|
|
32
|
+
context = getContext(EDITOR_ENABLED_KEY);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// called outside component -> ignore, we’ll use global store
|
|
36
|
+
}
|
|
37
|
+
if (!context) {
|
|
38
|
+
return createEditorEnabledClient();
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DictionaryKeys, KeyPath } from '@intlayer/types';
|
|
2
|
-
import { Writable } from 'svelte/store';
|
|
1
|
+
import type { DictionaryKeys, KeyPath } from '@intlayer/types';
|
|
2
|
+
import type { Writable } from 'svelte/store';
|
|
3
3
|
export type FocusedContent = {
|
|
4
4
|
dictionaryKey: DictionaryKeys;
|
|
5
5
|
keyPath: KeyPath[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MessageKey } from '@intlayer/editor';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { useCrossFrameState } from './useCrossFrameState';
|
|
4
|
+
const FOCUS_DICTIONARY_KEY = Symbol('FOCUS_DICTIONARY');
|
|
5
|
+
export const createFocusDictionaryClient = () => {
|
|
6
|
+
const [focusedContent, setFocusedContent] = useCrossFrameState(MessageKey.INTLAYER_FOCUSED_CONTENT_CHANGED, null);
|
|
7
|
+
setContext(FOCUS_DICTIONARY_KEY, { focusedContent, setFocusedContent });
|
|
8
|
+
return { focusedContent, setFocusedContent };
|
|
9
|
+
};
|
|
10
|
+
export const useFocusDictionary = () => {
|
|
11
|
+
let context;
|
|
12
|
+
try {
|
|
13
|
+
context = getContext(FOCUS_DICTIONARY_KEY);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// called outside component -> ignore, we’ll use global store
|
|
17
|
+
}
|
|
18
|
+
if (!context) {
|
|
19
|
+
return createFocusDictionaryClient();
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as ContentSelector } from './ContentSelector.svelte';
|
|
2
|
+
export { default as ContentSelectorWrapper } from './ContentSelectorWrapper.svelte';
|
|
3
|
+
export * from './communicator';
|
|
4
|
+
export * from './editorEnabled';
|
|
5
|
+
export * from './focusDictionary';
|
|
6
|
+
export * from './useCrossFrameMessageListener';
|
|
7
|
+
export * from './useCrossFrameState';
|
|
8
|
+
export * from './useEditor';
|
|
9
|
+
export * from './useIframeClickInterceptor';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { MessageKey } from '@intlayer/editor';
|
|
1
|
+
import { type MessageKey } from '@intlayer/editor';
|
|
2
2
|
export declare const useCrossFrameMessageListener: <S>(key: `${MessageKey}` | `${MessageKey}/post` | `${MessageKey}/get`, onEventTriggered?: (data: S) => void, autoCleanup?: boolean) => (data?: S) => void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { compareUrls } from '@intlayer/editor';
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
3
|
+
import { get } from 'svelte/store';
|
|
4
|
+
import { useCommunicator } from './communicator';
|
|
5
|
+
const subscribers = new Map();
|
|
6
|
+
let windowListenerAttached = false;
|
|
7
|
+
const addSubscriber = (key, cb) => {
|
|
8
|
+
let set = subscribers.get(key);
|
|
9
|
+
if (!set) {
|
|
10
|
+
set = new Set();
|
|
11
|
+
subscribers.set(key, set);
|
|
12
|
+
}
|
|
13
|
+
set.add(cb);
|
|
14
|
+
};
|
|
15
|
+
const removeSubscriber = (key, cb) => {
|
|
16
|
+
const set = subscribers.get(key);
|
|
17
|
+
if (!set)
|
|
18
|
+
return;
|
|
19
|
+
set.delete(cb);
|
|
20
|
+
if (set.size === 0)
|
|
21
|
+
subscribers.delete(key);
|
|
22
|
+
};
|
|
23
|
+
const ensureGlobalListener = (allowedOrigins, selfId) => {
|
|
24
|
+
if (windowListenerAttached)
|
|
25
|
+
return;
|
|
26
|
+
if (typeof window === 'undefined')
|
|
27
|
+
return;
|
|
28
|
+
window.addEventListener('message', (event) => {
|
|
29
|
+
const { type, data, senderId } = event.data ?? {};
|
|
30
|
+
if (!type)
|
|
31
|
+
return;
|
|
32
|
+
if (senderId === selfId)
|
|
33
|
+
return;
|
|
34
|
+
if (!allowedOrigins ||
|
|
35
|
+
allowedOrigins.includes('*') ||
|
|
36
|
+
allowedOrigins.some((o) => compareUrls(o, event.origin))) {
|
|
37
|
+
subscribers.get(type)?.forEach((cb) => {
|
|
38
|
+
cb(data);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
windowListenerAttached = true;
|
|
43
|
+
};
|
|
44
|
+
export const useCrossFrameMessageListener = (key, onEventTriggered, autoCleanup = true) => {
|
|
45
|
+
const communicatorStore = useCommunicator();
|
|
46
|
+
const { allowedOrigins, senderId } = get(communicatorStore);
|
|
47
|
+
ensureGlobalListener(allowedOrigins, senderId);
|
|
48
|
+
if (onEventTriggered) {
|
|
49
|
+
const cb = onEventTriggered;
|
|
50
|
+
addSubscriber(key, cb);
|
|
51
|
+
if (autoCleanup) {
|
|
52
|
+
try {
|
|
53
|
+
onDestroy(() => removeSubscriber(key, cb));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Might be called outside component, manual cleanup needed if needed
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const postMessageWrapper = (data) => {
|
|
61
|
+
const { postMessage, senderId: currentSenderId } = get(communicatorStore);
|
|
62
|
+
postMessage({ type: key, data, senderId: currentSenderId }, '*');
|
|
63
|
+
};
|
|
64
|
+
return postMessageWrapper;
|
|
65
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MessageKey } from '@intlayer/editor';
|
|
2
|
-
import { Writable } from 'svelte/store';
|
|
1
|
+
import type { MessageKey } from '@intlayer/editor';
|
|
2
|
+
import { type Writable } from 'svelte/store';
|
|
3
3
|
export type CrossFrameStateOptions = {
|
|
4
4
|
emit?: boolean;
|
|
5
5
|
receive?: boolean;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { get, writable } from 'svelte/store';
|
|
2
|
+
import { useCommunicator } from './communicator';
|
|
3
|
+
import { useCrossFrameMessageListener } from './useCrossFrameMessageListener';
|
|
4
|
+
const crossFrameStateCache = new Map();
|
|
5
|
+
const resolveState = (state, prevState) => {
|
|
6
|
+
if (typeof state === 'function') {
|
|
7
|
+
return state(prevState);
|
|
8
|
+
}
|
|
9
|
+
return state;
|
|
10
|
+
};
|
|
11
|
+
const toSerializable = (obj) => {
|
|
12
|
+
if (obj === null || obj === undefined)
|
|
13
|
+
return obj;
|
|
14
|
+
return JSON.parse(JSON.stringify(obj));
|
|
15
|
+
};
|
|
16
|
+
export const useCrossFrameState = (key, initialState, options = { emit: true, receive: true }) => {
|
|
17
|
+
if (crossFrameStateCache.has(key)) {
|
|
18
|
+
const { state, setState } = crossFrameStateCache.get(key);
|
|
19
|
+
return [state, setState];
|
|
20
|
+
}
|
|
21
|
+
const { emit = true, receive = true } = options;
|
|
22
|
+
// Initialize state
|
|
23
|
+
const initialValue = resolveState(initialState);
|
|
24
|
+
const state = writable(initialValue);
|
|
25
|
+
const communicatorStore = useCommunicator();
|
|
26
|
+
const broadcastState = (value) => {
|
|
27
|
+
const { postMessage, senderId } = get(communicatorStore);
|
|
28
|
+
if (!emit ||
|
|
29
|
+
typeof postMessage !== 'function' ||
|
|
30
|
+
typeof value === 'undefined') {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
postMessage({
|
|
34
|
+
type: `${key}/post`,
|
|
35
|
+
data: value,
|
|
36
|
+
senderId,
|
|
37
|
+
}, '*');
|
|
38
|
+
};
|
|
39
|
+
const setState = (valueOrUpdater) => {
|
|
40
|
+
state.update((prev) => {
|
|
41
|
+
const next = resolveState(valueOrUpdater, prev);
|
|
42
|
+
const serialised = toSerializable(next);
|
|
43
|
+
broadcastState(serialised);
|
|
44
|
+
return serialised;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const postState = () => {
|
|
48
|
+
const { postMessage, senderId } = get(communicatorStore);
|
|
49
|
+
if (typeof postMessage !== 'function')
|
|
50
|
+
return;
|
|
51
|
+
postMessage({
|
|
52
|
+
type: `${key}/post`,
|
|
53
|
+
data: get(state),
|
|
54
|
+
senderId,
|
|
55
|
+
}, '*');
|
|
56
|
+
};
|
|
57
|
+
// Emit initial state
|
|
58
|
+
broadcastState(initialValue);
|
|
59
|
+
// If receiving, ask for state
|
|
60
|
+
if (receive && typeof get(state) === 'undefined') {
|
|
61
|
+
const { postMessage, senderId } = get(communicatorStore);
|
|
62
|
+
if (typeof postMessage === 'function') {
|
|
63
|
+
postMessage({ type: `${key}/get`, senderId }, '*');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Listen for updates
|
|
67
|
+
const listenerKey = receive ? `${key}/post` : `${key}/ignore`;
|
|
68
|
+
const listener = useCrossFrameMessageListener(listenerKey, (data) => {
|
|
69
|
+
if (receive) {
|
|
70
|
+
state.set(data);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
// Listen for requests
|
|
74
|
+
const getListenerKey = emit ? `${key}/get` : `${key}/ignore`;
|
|
75
|
+
const getListener = useCrossFrameMessageListener(getListenerKey, (_) => {
|
|
76
|
+
if (emit) {
|
|
77
|
+
broadcastState(get(state));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
crossFrameStateCache.set(key, { state, setState, postState });
|
|
81
|
+
return [state, setState];
|
|
82
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { MessageKey } from '@intlayer/editor';
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
3
|
+
import { get } from 'svelte/store';
|
|
4
|
+
import { useDictionariesRecord } from './dictionariesRecord';
|
|
5
|
+
import { useEditorEnabled } from './editorEnabled';
|
|
6
|
+
import { useCrossFrameMessageListener } from './useCrossFrameMessageListener';
|
|
7
|
+
import { useIframeClickMerger } from './useIframeClickInterceptor';
|
|
8
|
+
let initialized = false;
|
|
9
|
+
let unsubscribeIsInIframe = null;
|
|
10
|
+
export const useEditor = () => {
|
|
11
|
+
if (typeof window === 'undefined')
|
|
12
|
+
return;
|
|
13
|
+
if (initialized)
|
|
14
|
+
return;
|
|
15
|
+
initialized = true;
|
|
16
|
+
const editorEnabled = useEditorEnabled();
|
|
17
|
+
useDictionariesRecord();
|
|
18
|
+
useIframeClickMerger();
|
|
19
|
+
// Listen for editor enabled
|
|
20
|
+
useCrossFrameMessageListener(`${MessageKey.INTLAYER_EDITOR_ENABLED}/post`, (data) => {
|
|
21
|
+
editorEnabled.wrapperEnabled.set(data);
|
|
22
|
+
}, false);
|
|
23
|
+
const getEditorEnabled = useCrossFrameMessageListener(`${MessageKey.INTLAYER_EDITOR_ENABLED}/get`, (data) => {
|
|
24
|
+
editorEnabled.wrapperEnabled.set(data);
|
|
25
|
+
}, false);
|
|
26
|
+
// Initial check
|
|
27
|
+
const checkEnabled = () => {
|
|
28
|
+
const inIframe = get(editorEnabled.isInIframe);
|
|
29
|
+
const setting = get(editorEnabled.settingEnabled);
|
|
30
|
+
if (inIframe && setting) {
|
|
31
|
+
getEditorEnabled();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
checkEnabled();
|
|
35
|
+
// Subscribe to changes
|
|
36
|
+
editorEnabled.isInIframe.subscribe(() => checkEnabled());
|
|
37
|
+
// Keep track of unsubscribe so we *could* clean up if we ever wanted
|
|
38
|
+
unsubscribeIsInIframe = editorEnabled.isInIframe.subscribe(() => checkEnabled());
|
|
39
|
+
onDestroy(() => {
|
|
40
|
+
initialized = false;
|
|
41
|
+
if (unsubscribeIsInIframe) {
|
|
42
|
+
unsubscribeIsInIframe();
|
|
43
|
+
unsubscribeIsInIframe = null;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MessageKey, mergeIframeClick } from '@intlayer/editor';
|
|
2
|
+
import { onDestroy, onMount } from 'svelte';
|
|
3
|
+
import { useCrossFrameMessageListener } from './useCrossFrameMessageListener';
|
|
4
|
+
export const useIframeClickInterceptor = () => {
|
|
5
|
+
const postMessage = useCrossFrameMessageListener(MessageKey.INTLAYER_IFRAME_CLICKED);
|
|
6
|
+
const handler = () => {
|
|
7
|
+
postMessage();
|
|
8
|
+
};
|
|
9
|
+
onMount(() => {
|
|
10
|
+
if (typeof window !== 'undefined') {
|
|
11
|
+
window.addEventListener('mousedown', handler);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
onDestroy(() => {
|
|
15
|
+
if (typeof window !== 'undefined') {
|
|
16
|
+
window.removeEventListener('mousedown', handler);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
export const useIframeClickMerger = () => {
|
|
21
|
+
useIframeClickInterceptor();
|
|
22
|
+
useCrossFrameMessageListener(MessageKey.INTLAYER_IFRAME_CLICKED, (data) => {
|
|
23
|
+
// mergeIframeClick(data); // mergeIframeClick expects an event, but data might be stripped?
|
|
24
|
+
// Actually mergeIframeClick logic in editor package probably dispatches a custom event or similar.
|
|
25
|
+
// The Vue implementation passes `mergeIframeClick` directly as the callback.
|
|
26
|
+
// Let's assume mergeIframeClick handles whatever data is passed, or we wrap it if needed.
|
|
27
|
+
mergeIframeClick(data);
|
|
28
|
+
});
|
|
29
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Plugins } from '@intlayer/core';
|
|
2
|
-
import { DeclaredLocales, Dictionary, LocalesValues } from '@intlayer/types';
|
|
3
|
-
import { DeepTransformContent } from './plugins';
|
|
1
|
+
import { type Plugins } from '@intlayer/core';
|
|
2
|
+
import type { DeclaredLocales, Dictionary, LocalesValues } from '@intlayer/types';
|
|
3
|
+
import { type DeepTransformContent } from './plugins';
|
|
4
4
|
/**
|
|
5
5
|
* Get dictionary content for a specific locale in Svelte applications
|
|
6
6
|
* @param dictionary The dictionary object to transform
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getDictionary as getDictionaryCore, } from '@intlayer/core';
|
|
2
|
+
import { intlayerNodePlugins, markdownPlugin, svelteNodePlugins, } from './plugins';
|
|
3
|
+
/**
|
|
4
|
+
* Get dictionary content for a specific locale in Svelte applications
|
|
5
|
+
* @param dictionary The dictionary object to transform
|
|
6
|
+
* @param locale The target locale (optional, defaults to current locale)
|
|
7
|
+
* @param additionalPlugins Additional transformation plugins
|
|
8
|
+
* @returns Transformed dictionary content optimized for Svelte
|
|
9
|
+
*/
|
|
10
|
+
export const getDictionary = (dictionary, locale, additionalPlugins) => {
|
|
11
|
+
const plugins = [
|
|
12
|
+
intlayerNodePlugins,
|
|
13
|
+
svelteNodePlugins,
|
|
14
|
+
markdownPlugin,
|
|
15
|
+
...(additionalPlugins ?? []),
|
|
16
|
+
];
|
|
17
|
+
return getDictionaryCore(dictionary, locale, plugins);
|
|
18
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Plugins } from '@intlayer/core';
|
|
2
|
-
import { DeclaredLocales, DictionaryKeys, DictionaryRegistryContent, LocalesValues } from '@intlayer/types';
|
|
3
|
-
import { DeepTransformContent } from './plugins';
|
|
1
|
+
import { type Plugins } from '@intlayer/core';
|
|
2
|
+
import type { DeclaredLocales, DictionaryKeys, DictionaryRegistryContent, LocalesValues } from '@intlayer/types';
|
|
3
|
+
import { type DeepTransformContent } from './plugins';
|
|
4
4
|
/**
|
|
5
5
|
* Get dictionary content by key for Svelte applications
|
|
6
6
|
* @param key The dictionary key to retrieve
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getIntlayer as getIntlayerCore } from '@intlayer/core';
|
|
2
|
+
import { intlayerNodePlugins, markdownPlugin, svelteNodePlugins, } from './plugins';
|
|
3
|
+
/**
|
|
4
|
+
* Get dictionary content by key for Svelte applications
|
|
5
|
+
* @param key The dictionary key to retrieve
|
|
6
|
+
* @param locale The target locale (optional)
|
|
7
|
+
* @param additionalPlugins Additional transformation plugins
|
|
8
|
+
* @returns Transformed dictionary content optimized for Svelte
|
|
9
|
+
*/
|
|
10
|
+
export const getIntlayer = (key, locale, additionalPlugins) => {
|
|
11
|
+
const plugins = [
|
|
12
|
+
intlayerNodePlugins,
|
|
13
|
+
svelteNodePlugins,
|
|
14
|
+
markdownPlugin,
|
|
15
|
+
...(additionalPlugins ?? []),
|
|
16
|
+
];
|
|
17
|
+
return getIntlayerCore(key, locale, plugins);
|
|
18
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { IInterpreterPluginSvelte } from './plugins';
|
|
2
|
-
import { useEditor } from './editor';
|
|
3
|
-
import { setMarkdownContext } from './markdown';
|
|
1
|
+
import type { IInterpreterPluginSvelte } from './plugins';
|
|
4
2
|
declare module '@intlayer/core' {
|
|
5
3
|
interface IInterpreterPlugin<T, S, L> extends IInterpreterPluginSvelte<T> {
|
|
6
4
|
}
|
|
@@ -9,4 +7,6 @@ export * from './client';
|
|
|
9
7
|
export * from './getDictionary';
|
|
10
8
|
export * from './getIntlayer';
|
|
11
9
|
export * from './plugins';
|
|
10
|
+
import { useEditor } from './editor';
|
|
11
|
+
import { setMarkdownContext } from './markdown';
|
|
12
12
|
export { useEditor as useIntlayerEditor, setMarkdownContext as setIntlayerMarkdown, };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './client';
|
|
2
|
+
export * from './getDictionary';
|
|
3
|
+
export * from './getIntlayer';
|
|
4
|
+
export * from './plugins';
|
|
5
|
+
import { useEditor } from './editor';
|
|
6
|
+
import { setMarkdownContext } from './markdown';
|
|
7
|
+
export { useEditor as useIntlayerEditor, setMarkdownContext as setIntlayerMarkdown, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|