@payloadcms/richtext-lexical 3.39.0-internal.32c7661 → 3.39.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/dist/exports/client/bundled.css +1 -1
- package/dist/exports/client/index.d.ts +1 -0
- package/dist/exports/client/index.d.ts.map +1 -1
- package/dist/exports/client/index.js +10 -10
- package/dist/exports/client/index.js.map +4 -4
- package/dist/features/experimental_table/client/utils/debounce.d.ts +4 -4
- package/dist/features/experimental_table/client/utils/debounce.js +4 -4
- package/dist/features/experimental_table/client/utils/debounce.js.map +1 -1
- package/dist/features/textState/defaultColors.d.ts +91 -0
- package/dist/features/textState/defaultColors.d.ts.map +1 -0
- package/dist/features/textState/defaultColors.js +386 -0
- package/dist/features/textState/defaultColors.js.map +1 -0
- package/dist/features/textState/feature.client.d.ts +3 -0
- package/dist/features/textState/feature.client.d.ts.map +1 -0
- package/dist/features/textState/feature.client.js +69 -0
- package/dist/features/textState/feature.client.js.map +1 -0
- package/dist/features/textState/feature.server.d.ts +60 -0
- package/dist/features/textState/feature.server.d.ts.map +1 -0
- package/dist/features/textState/feature.server.js +25 -0
- package/dist/features/textState/feature.server.js.map +1 -0
- package/dist/features/textState/textState.d.ts +6 -0
- package/dist/features/textState/textState.d.ts.map +1 -0
- package/dist/features/textState/textState.js +67 -0
- package/dist/features/textState/textState.js.map +1 -0
- package/dist/field/bundled.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lexical/ui/icons/TextState/index.d.ts +5 -0
- package/dist/lexical/ui/icons/TextState/index.d.ts.map +1 -0
- package/dist/lexical/ui/icons/TextState/index.js +23 -0
- package/dist/lexical/ui/icons/TextState/index.js.map +1 -0
- package/package.json +8 -7
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
import { TextStateIcon } from '../../lexical/ui/icons/TextState/index.js';
|
|
5
|
+
import { createClientFeature } from '../../utilities/createClientFeature.js';
|
|
6
|
+
import { registerTextStates, setTextState, StatePlugin } from './textState.js';
|
|
7
|
+
const toolbarGroups = props => {
|
|
8
|
+
const items = [];
|
|
9
|
+
for (const stateKey in props.state) {
|
|
10
|
+
const key = props.state[stateKey];
|
|
11
|
+
for (const stateValue in key) {
|
|
12
|
+
const meta = key[stateValue];
|
|
13
|
+
items.push({
|
|
14
|
+
ChildComponent: () => /*#__PURE__*/_jsx(TextStateIcon, {
|
|
15
|
+
css: meta.css
|
|
16
|
+
}),
|
|
17
|
+
key: stateValue,
|
|
18
|
+
label: meta.label,
|
|
19
|
+
onSelect: ({
|
|
20
|
+
editor
|
|
21
|
+
}) => {
|
|
22
|
+
setTextState(editor, stateKey, stateValue);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const clearStyle = [{
|
|
28
|
+
ChildComponent: () => /*#__PURE__*/_jsx(TextStateIcon, {}),
|
|
29
|
+
key: `clear-style`,
|
|
30
|
+
label: 'Default style',
|
|
31
|
+
onSelect: ({
|
|
32
|
+
editor
|
|
33
|
+
}) => {
|
|
34
|
+
for (const stateKey in props.state) {
|
|
35
|
+
setTextState(editor, stateKey, undefined);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
order: 1
|
|
39
|
+
}];
|
|
40
|
+
return [{
|
|
41
|
+
type: 'dropdown',
|
|
42
|
+
ChildComponent: () => /*#__PURE__*/_jsx(TextStateIcon, {
|
|
43
|
+
css: {
|
|
44
|
+
color: 'var(--theme-elevation-600)'
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
items: [...clearStyle, ...items],
|
|
48
|
+
key: 'textState',
|
|
49
|
+
order: 30
|
|
50
|
+
}];
|
|
51
|
+
};
|
|
52
|
+
export const TextStateFeatureClient = createClientFeature(({
|
|
53
|
+
props
|
|
54
|
+
}) => {
|
|
55
|
+
registerTextStates(props.state);
|
|
56
|
+
return {
|
|
57
|
+
plugins: [{
|
|
58
|
+
Component: StatePlugin,
|
|
59
|
+
position: 'normal'
|
|
60
|
+
}],
|
|
61
|
+
toolbarFixed: {
|
|
62
|
+
groups: toolbarGroups(props)
|
|
63
|
+
},
|
|
64
|
+
toolbarInline: {
|
|
65
|
+
groups: toolbarGroups(props)
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=feature.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.client.js","names":["TextStateIcon","createClientFeature","registerTextStates","setTextState","StatePlugin","toolbarGroups","props","items","stateKey","state","key","stateValue","meta","push","ChildComponent","_jsx","css","label","onSelect","editor","clearStyle","undefined","order","type","color","TextStateFeatureClient","plugins","Component","position","toolbarFixed","groups","toolbarInline"],"sources":["../../../src/features/textState/feature.client.tsx"],"sourcesContent":["'use client'\n\nimport type { ToolbarDropdownGroup, ToolbarGroup } from '../toolbars/types.js'\nimport type { TextStateFeatureProps } from './feature.server.js'\n\nimport { TextStateIcon } from '../../lexical/ui/icons/TextState/index.js'\nimport { createClientFeature } from '../../utilities/createClientFeature.js'\nimport { registerTextStates, setTextState, StatePlugin } from './textState.js'\n\nconst toolbarGroups = (props: TextStateFeatureProps): ToolbarGroup[] => {\n const items: ToolbarDropdownGroup['items'] = []\n\n for (const stateKey in props.state) {\n const key = props.state[stateKey]!\n for (const stateValue in key) {\n const meta = key[stateValue]!\n items.push({\n ChildComponent: () => <TextStateIcon css={meta.css} />,\n key: stateValue,\n label: meta.label,\n onSelect: ({ editor }) => {\n setTextState(editor, stateKey, stateValue)\n },\n })\n }\n }\n\n const clearStyle: ToolbarDropdownGroup['items'] = [\n {\n ChildComponent: () => <TextStateIcon />,\n key: `clear-style`,\n label: 'Default style',\n onSelect: ({ editor }) => {\n for (const stateKey in props.state) {\n setTextState(editor, stateKey, undefined)\n }\n },\n order: 1,\n },\n ]\n\n return [\n {\n type: 'dropdown',\n ChildComponent: () => <TextStateIcon css={{ color: 'var(--theme-elevation-600)' }} />,\n items: [...clearStyle, ...items],\n key: 'textState',\n order: 30,\n },\n ]\n}\n\nexport const TextStateFeatureClient = createClientFeature<TextStateFeatureProps>(({ props }) => {\n registerTextStates(props.state)\n return {\n plugins: [\n {\n Component: StatePlugin,\n position: 'normal',\n },\n ],\n toolbarFixed: {\n groups: toolbarGroups(props),\n },\n toolbarInline: {\n groups: toolbarGroups(props),\n },\n }\n})\n"],"mappings":"AAAA;;;AAKA,SAASA,aAAa,QAAQ;AAC9B,SAASC,mBAAmB,QAAQ;AACpC,SAASC,kBAAkB,EAAEC,YAAY,EAAEC,WAAW,QAAQ;AAE9D,MAAMC,aAAA,GAAiBC,KAAA;EACrB,MAAMC,KAAA,GAAuC,EAAE;EAE/C,KAAK,MAAMC,QAAA,IAAYF,KAAA,CAAMG,KAAK,EAAE;IAClC,MAAMC,GAAA,GAAMJ,KAAA,CAAMG,KAAK,CAACD,QAAA,CAAS;IACjC,KAAK,MAAMG,UAAA,IAAcD,GAAA,EAAK;MAC5B,MAAME,IAAA,GAAOF,GAAG,CAACC,UAAA,CAAW;MAC5BJ,KAAA,CAAMM,IAAI,CAAC;QACTC,cAAA,EAAgBA,CAAA,kBAAMC,IAAA,CAACf,aAAA;UAAcgB,GAAA,EAAKJ,IAAA,CAAKI;;QAC/CN,GAAA,EAAKC,UAAA;QACLM,KAAA,EAAOL,IAAA,CAAKK,KAAK;QACjBC,QAAA,EAAUA,CAAC;UAAEC;QAAM,CAAE;UACnBhB,YAAA,CAAagB,MAAA,EAAQX,QAAA,EAAUG,UAAA;QACjC;MACF;IACF;EACF;EAEA,MAAMS,UAAA,GAA4C,CAChD;IACEN,cAAA,EAAgBA,CAAA,kBAAMC,IAAA,CAACf,aAAA;IACvBU,GAAA,EAAK,aAAa;IAClBO,KAAA,EAAO;IACPC,QAAA,EAAUA,CAAC;MAAEC;IAAM,CAAE;MACnB,KAAK,MAAMX,QAAA,IAAYF,KAAA,CAAMG,KAAK,EAAE;QAClCN,YAAA,CAAagB,MAAA,EAAQX,QAAA,EAAUa,SAAA;MACjC;IACF;IACAC,KAAA,EAAO;EACT,EACD;EAED,OAAO,CACL;IACEC,IAAA,EAAM;IACNT,cAAA,EAAgBA,CAAA,kBAAMC,IAAA,CAACf,aAAA;MAAcgB,GAAA,EAAK;QAAEQ,KAAA,EAAO;MAA6B;;IAChFjB,KAAA,EAAO,C,GAAIa,UAAA,E,GAAeb,KAAA,CAAM;IAChCG,GAAA,EAAK;IACLY,KAAA,EAAO;EACT,EACD;AACH;AAEA,OAAO,MAAMG,sBAAA,GAAyBxB,mBAAA,CAA2C,CAAC;EAAEK;AAAK,CAAE;EACzFJ,kBAAA,CAAmBI,KAAA,CAAMG,KAAK;EAC9B,OAAO;IACLiB,OAAA,EAAS,CACP;MACEC,SAAA,EAAWvB,WAAA;MACXwB,QAAA,EAAU;IACZ,EACD;IACDC,YAAA,EAAc;MACZC,MAAA,EAAQzB,aAAA,CAAcC,KAAA;IACxB;IACAyB,aAAA,EAAe;MACbD,MAAA,EAAQzB,aAAA,CAAcC,KAAA;IACxB;EACF;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { PropertiesHyphenFallback } from 'csstype';
|
|
2
|
+
import type { Prettify } from 'ts-essentials';
|
|
3
|
+
export type StyleObject = Prettify<{
|
|
4
|
+
[K in keyof PropertiesHyphenFallback]?: Extract<PropertiesHyphenFallback[K], string> | undefined;
|
|
5
|
+
}>;
|
|
6
|
+
export type StateValues = {
|
|
7
|
+
[stateValue: string]: {
|
|
8
|
+
css: StyleObject;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type TextStateFeatureProps = {
|
|
13
|
+
/**
|
|
14
|
+
* The keys of the top-level object (stateKeys) represent the attributes that the textNode can have (e.g., color).
|
|
15
|
+
* The values of the top-level object (stateValues) represent the values that the attribute can have (e.g., red, blue, etc.).
|
|
16
|
+
* Within the stateValue, you can define inline styles and labels.
|
|
17
|
+
*
|
|
18
|
+
* @note Because this is a common use case, we provide a defaultColors object with colors that
|
|
19
|
+
* look good in both dark and light mode, which you can use or adapt to your liking.
|
|
20
|
+
*
|
|
21
|
+
*
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import { defaultColors } from '@payloadcms/richtext-lexical'
|
|
25
|
+
*
|
|
26
|
+
* state: {
|
|
27
|
+
* color: {
|
|
28
|
+
* ...defaultColors.background,
|
|
29
|
+
* ...defaultColors.text,
|
|
30
|
+
* // fancy gradients!
|
|
31
|
+
* galaxy: { label: 'Galaxy', css: { background: 'linear-gradient(to right, #0000ff, #ff0000)', color: 'white' } },
|
|
32
|
+
* sunset: { label: 'Sunset', css: { background: 'linear-gradient(to top, #ff5f6d, #6a3093)' } },
|
|
33
|
+
* },
|
|
34
|
+
* // You can have both colored and underlined text at the same time.
|
|
35
|
+
* // If you don't want that, you should group them within the same key.
|
|
36
|
+
* // (just like I did with defaultColors and my fancy gradients)
|
|
37
|
+
* underline: {
|
|
38
|
+
* 'solid': { label: 'Solid', css: { 'text-decoration': 'underline', 'text-underline-offset': '4px' } },
|
|
39
|
+
* // You'll probably want to use the CSS light-dark() utility.
|
|
40
|
+
* 'yellow-dashed': { label: 'Yellow Dashed', css: { 'text-decoration': 'underline dashed', 'text-decoration-color': 'light-dark(#EAB308,yellow)', 'text-underline-offset': '4px' } },
|
|
41
|
+
* },
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
state: {
|
|
46
|
+
[stateKey: string]: StateValues;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Allows you to store key-value attributes within TextNodes and define inline styles for each combination.
|
|
51
|
+
* Inline styles are not part of the editorState, reducing the JSON size and allowing you to easily migrate or adapt styles later.
|
|
52
|
+
*
|
|
53
|
+
* This feature can be used, among other things, to add colors to text.
|
|
54
|
+
*
|
|
55
|
+
* For more information and examples, see the JSdocs for the "state" property that this feature receives as a parameter.
|
|
56
|
+
*
|
|
57
|
+
* @experimental There may be breaking changes to this API
|
|
58
|
+
*/
|
|
59
|
+
export declare const TextStateFeature: import("../typesServer.js").FeatureProviderProviderServer<TextStateFeatureProps, TextStateFeatureProps, TextStateFeatureProps>;
|
|
60
|
+
//# sourceMappingURL=feature.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.server.d.ts","sourceRoot":"","sources":["../../../src/features/textState/feature.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAK7C,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;KAChC,CAAC,IAAI,MAAM,wBAAwB,CAAC,CAAC,EAClC,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,GAG5C,SAAS;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG;IAAE,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAA;AAEvF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,KAAK,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAA;KAAE,CAAA;CAC3C,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,gIAc3B,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createServerFeature } from '../../utilities/createServerFeature.js';
|
|
2
|
+
/**
|
|
3
|
+
* Allows you to store key-value attributes within TextNodes and define inline styles for each combination.
|
|
4
|
+
* Inline styles are not part of the editorState, reducing the JSON size and allowing you to easily migrate or adapt styles later.
|
|
5
|
+
*
|
|
6
|
+
* This feature can be used, among other things, to add colors to text.
|
|
7
|
+
*
|
|
8
|
+
* For more information and examples, see the JSdocs for the "state" property that this feature receives as a parameter.
|
|
9
|
+
*
|
|
10
|
+
* @experimental There may be breaking changes to this API
|
|
11
|
+
*/
|
|
12
|
+
export const TextStateFeature = createServerFeature({
|
|
13
|
+
feature: ({
|
|
14
|
+
props
|
|
15
|
+
}) => {
|
|
16
|
+
return {
|
|
17
|
+
ClientFeature: '@payloadcms/richtext-lexical/client#TextStateFeatureClient',
|
|
18
|
+
clientFeatureProps: {
|
|
19
|
+
state: props.state
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
key: 'textState'
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=feature.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.server.js","names":["createServerFeature","TextStateFeature","feature","props","ClientFeature","clientFeatureProps","state","key"],"sources":["../../../src/features/textState/feature.server.ts"],"sourcesContent":["import type { PropertiesHyphenFallback } from 'csstype'\nimport type { Prettify } from 'ts-essentials'\n\nimport { createServerFeature } from '../../utilities/createServerFeature.js'\n\n// extracted from https://github.com/facebook/lexical/pull/7294\nexport type StyleObject = Prettify<{\n [K in keyof PropertiesHyphenFallback]?:\n | Extract<PropertiesHyphenFallback[K], string>\n // This is simplified to not deal with arrays or numbers.\n // This is an example after all!\n | undefined\n}>\n\nexport type StateValues = { [stateValue: string]: { css: StyleObject; label: string } }\n\nexport type TextStateFeatureProps = {\n /**\n * The keys of the top-level object (stateKeys) represent the attributes that the textNode can have (e.g., color).\n * The values of the top-level object (stateValues) represent the values that the attribute can have (e.g., red, blue, etc.).\n * Within the stateValue, you can define inline styles and labels.\n *\n * @note Because this is a common use case, we provide a defaultColors object with colors that\n * look good in both dark and light mode, which you can use or adapt to your liking.\n *\n *\n *\n * @example\n * import { defaultColors } from '@payloadcms/richtext-lexical'\n *\n * state: {\n * color: {\n * ...defaultColors.background,\n * ...defaultColors.text,\n * // fancy gradients!\n * galaxy: { label: 'Galaxy', css: { background: 'linear-gradient(to right, #0000ff, #ff0000)', color: 'white' } },\n * sunset: { label: 'Sunset', css: { background: 'linear-gradient(to top, #ff5f6d, #6a3093)' } },\n * },\n * // You can have both colored and underlined text at the same time.\n * // If you don't want that, you should group them within the same key.\n * // (just like I did with defaultColors and my fancy gradients)\n * underline: {\n * 'solid': { label: 'Solid', css: { 'text-decoration': 'underline', 'text-underline-offset': '4px' } },\n * // You'll probably want to use the CSS light-dark() utility.\n * 'yellow-dashed': { label: 'Yellow Dashed', css: { 'text-decoration': 'underline dashed', 'text-decoration-color': 'light-dark(#EAB308,yellow)', 'text-underline-offset': '4px' } },\n * },\n * }\n *\n */\n state: { [stateKey: string]: StateValues }\n}\n\n/**\n * Allows you to store key-value attributes within TextNodes and define inline styles for each combination.\n * Inline styles are not part of the editorState, reducing the JSON size and allowing you to easily migrate or adapt styles later.\n *\n * This feature can be used, among other things, to add colors to text.\n *\n * For more information and examples, see the JSdocs for the \"state\" property that this feature receives as a parameter.\n *\n * @experimental There may be breaking changes to this API\n */\nexport const TextStateFeature = createServerFeature<\n TextStateFeatureProps,\n TextStateFeatureProps,\n TextStateFeatureProps\n>({\n feature: ({ props }) => {\n return {\n ClientFeature: '@payloadcms/richtext-lexical/client#TextStateFeatureClient',\n clientFeatureProps: {\n state: props.state,\n },\n }\n },\n key: 'textState',\n})\n"],"mappings":"AAGA,SAASA,mBAAmB,QAAQ;AAiDpC;;;;;;;;;;AAUA,OAAO,MAAMC,gBAAA,GAAmBD,mBAAA,CAI9B;EACAE,OAAA,EAASA,CAAC;IAAEC;EAAK,CAAE;IACjB,OAAO;MACLC,aAAA,EAAe;MACfC,kBAAA,EAAoB;QAClBC,KAAA,EAAOH,KAAA,CAAMG;MACf;IACF;EACF;EACAC,GAAA,EAAK;AACP","ignoreList":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LexicalEditor } from 'lexical';
|
|
2
|
+
import { type TextStateFeatureProps } from './feature.server.js';
|
|
3
|
+
export declare function registerTextStates(state: TextStateFeatureProps['state']): void;
|
|
4
|
+
export declare function setTextState(editor: LexicalEditor, stateKey: string, value: string | undefined): void;
|
|
5
|
+
export declare function StatePlugin(): null;
|
|
6
|
+
//# sourceMappingURL=textState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textState.d.ts","sourceRoot":"","sources":["../../../src/features/textState/textState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,SAAS,CAAA;AAOzD,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAUlF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,QASvE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,QAU9F;AAED,wBAAgB,WAAW,SAuC1B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
2
|
+
import { $forEachSelectedTextNode } from '@lexical/selection';
|
|
3
|
+
import { $getNodeByKey, $getState, $setState, createState, TextNode } from 'lexical';
|
|
4
|
+
import { useEffect } from 'react';
|
|
5
|
+
const stateMap = new Map();
|
|
6
|
+
export function registerTextStates(state) {
|
|
7
|
+
for (const stateKey in state) {
|
|
8
|
+
const stateValues = state[stateKey];
|
|
9
|
+
const stateConfig = createState(stateKey, {
|
|
10
|
+
parse: value => typeof value === 'string' && Object.keys(stateValues).includes(value) ? value : undefined
|
|
11
|
+
});
|
|
12
|
+
stateMap.set(stateKey, {
|
|
13
|
+
stateConfig,
|
|
14
|
+
stateValues
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function setTextState(editor, stateKey, value) {
|
|
19
|
+
editor.update(() => {
|
|
20
|
+
$forEachSelectedTextNode(textNode => {
|
|
21
|
+
const stateMapEntry = stateMap.get(stateKey);
|
|
22
|
+
if (!stateMapEntry) {
|
|
23
|
+
throw new Error(`State config for ${stateKey} not found`);
|
|
24
|
+
}
|
|
25
|
+
$setState(textNode, stateMapEntry.stateConfig, value);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function StatePlugin() {
|
|
30
|
+
const [editor] = useLexicalComposerContext();
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
return editor.registerMutationListener(TextNode, mutatedNodes => {
|
|
33
|
+
editor.getEditorState().read(() => {
|
|
34
|
+
for (const [nodeKey, mutation] of mutatedNodes) {
|
|
35
|
+
if (mutation === 'destroyed') {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const node = $getNodeByKey(nodeKey);
|
|
39
|
+
const dom = editor.getElementByKey(nodeKey);
|
|
40
|
+
if (!node || !dom) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// stateKey could be color for example
|
|
44
|
+
stateMap.forEach((stateEntry, _stateKey) => {
|
|
45
|
+
// stateValue could be bg-red for example
|
|
46
|
+
const stateValue = $getState(node, stateEntry.stateConfig);
|
|
47
|
+
if (!stateValue) {
|
|
48
|
+
delete dom.dataset[_stateKey];
|
|
49
|
+
dom.style.cssText = '';
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
dom.dataset[_stateKey] = stateValue;
|
|
53
|
+
const css = stateEntry.stateValues[stateValue]?.css;
|
|
54
|
+
if (!css) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
Object.entries(css).forEach(([key, value]) => {
|
|
58
|
+
dom.style.setProperty(key, value);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}, [editor]);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=textState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textState.js","names":["useLexicalComposerContext","$forEachSelectedTextNode","$getNodeByKey","$getState","$setState","createState","TextNode","useEffect","stateMap","Map","registerTextStates","state","stateKey","stateValues","stateConfig","parse","value","Object","keys","includes","undefined","set","setTextState","editor","update","textNode","stateMapEntry","get","Error","StatePlugin","registerMutationListener","mutatedNodes","getEditorState","read","nodeKey","mutation","node","dom","getElementByKey","forEach","stateEntry","_stateKey","stateValue","dataset","style","cssText","css","entries","key","setProperty"],"sources":["../../../src/features/textState/textState.ts"],"sourcesContent":["import type { LexicalEditor, StateConfig } from 'lexical'\n\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'\nimport { $forEachSelectedTextNode } from '@lexical/selection'\nimport { $getNodeByKey, $getState, $setState, createState, TextNode } from 'lexical'\nimport { useEffect } from 'react'\n\nimport { type StateValues, type TextStateFeatureProps } from './feature.server.js'\n\nconst stateMap = new Map<\n string,\n {\n stateConfig: StateConfig<string, string | undefined>\n stateValues: StateValues\n }\n>()\n\nexport function registerTextStates(state: TextStateFeatureProps['state']) {\n for (const stateKey in state) {\n const stateValues = state[stateKey]!\n const stateConfig = createState(stateKey, {\n parse: (value) =>\n typeof value === 'string' && Object.keys(stateValues).includes(value) ? value : undefined,\n })\n stateMap.set(stateKey, { stateConfig, stateValues })\n }\n}\n\nexport function setTextState(editor: LexicalEditor, stateKey: string, value: string | undefined) {\n editor.update(() => {\n $forEachSelectedTextNode((textNode) => {\n const stateMapEntry = stateMap.get(stateKey)\n if (!stateMapEntry) {\n throw new Error(`State config for ${stateKey} not found`)\n }\n $setState(textNode, stateMapEntry.stateConfig, value)\n })\n })\n}\n\nexport function StatePlugin() {\n const [editor] = useLexicalComposerContext()\n\n useEffect(() => {\n return editor.registerMutationListener(TextNode, (mutatedNodes) => {\n editor.getEditorState().read(() => {\n for (const [nodeKey, mutation] of mutatedNodes) {\n if (mutation === 'destroyed') {\n continue\n }\n const node = $getNodeByKey(nodeKey)\n const dom = editor.getElementByKey(nodeKey)\n if (!node || !dom) {\n continue\n }\n // stateKey could be color for example\n stateMap.forEach((stateEntry, _stateKey) => {\n // stateValue could be bg-red for example\n const stateValue = $getState(node, stateEntry.stateConfig)\n if (!stateValue) {\n delete dom.dataset[_stateKey]\n dom.style.cssText = ''\n return\n }\n dom.dataset[_stateKey] = stateValue\n const css = stateEntry.stateValues[stateValue]?.css\n if (!css) {\n return\n }\n Object.entries(css).forEach(([key, value]) => {\n dom.style.setProperty(key, value)\n })\n })\n }\n })\n })\n }, [editor])\n\n return null\n}\n"],"mappings":"AAEA,SAASA,yBAAyB,QAAQ;AAC1C,SAASC,wBAAwB,QAAQ;AACzC,SAASC,aAAa,EAAEC,SAAS,EAAEC,SAAS,EAAEC,WAAW,EAAEC,QAAQ,QAAQ;AAC3E,SAASC,SAAS,QAAQ;AAI1B,MAAMC,QAAA,GAAW,IAAIC,GAAA;AAQrB,OAAO,SAASC,mBAAmBC,KAAqC;EACtE,KAAK,MAAMC,QAAA,IAAYD,KAAA,EAAO;IAC5B,MAAME,WAAA,GAAcF,KAAK,CAACC,QAAA,CAAS;IACnC,MAAME,WAAA,GAAcT,WAAA,CAAYO,QAAA,EAAU;MACxCG,KAAA,EAAQC,KAAA,IACN,OAAOA,KAAA,KAAU,YAAYC,MAAA,CAAOC,IAAI,CAACL,WAAA,EAAaM,QAAQ,CAACH,KAAA,IAASA,KAAA,GAAQI;IACpF;IACAZ,QAAA,CAASa,GAAG,CAACT,QAAA,EAAU;MAAEE,WAAA;MAAaD;IAAY;EACpD;AACF;AAEA,OAAO,SAASS,aAAaC,MAAqB,EAAEX,QAAgB,EAAEI,KAAyB;EAC7FO,MAAA,CAAOC,MAAM,CAAC;IACZvB,wBAAA,CAA0BwB,QAAA;MACxB,MAAMC,aAAA,GAAgBlB,QAAA,CAASmB,GAAG,CAACf,QAAA;MACnC,IAAI,CAACc,aAAA,EAAe;QAClB,MAAM,IAAIE,KAAA,CAAM,oBAAoBhB,QAAA,YAAoB;MAC1D;MACAR,SAAA,CAAUqB,QAAA,EAAUC,aAAA,CAAcZ,WAAW,EAAEE,KAAA;IACjD;EACF;AACF;AAEA,OAAO,SAASa,YAAA;EACd,MAAM,CAACN,MAAA,CAAO,GAAGvB,yBAAA;EAEjBO,SAAA,CAAU;IACR,OAAOgB,MAAA,CAAOO,wBAAwB,CAACxB,QAAA,EAAWyB,YAAA;MAChDR,MAAA,CAAOS,cAAc,GAAGC,IAAI,CAAC;QAC3B,KAAK,MAAM,CAACC,OAAA,EAASC,QAAA,CAAS,IAAIJ,YAAA,EAAc;UAC9C,IAAII,QAAA,KAAa,aAAa;YAC5B;UACF;UACA,MAAMC,IAAA,GAAOlC,aAAA,CAAcgC,OAAA;UAC3B,MAAMG,GAAA,GAAMd,MAAA,CAAOe,eAAe,CAACJ,OAAA;UACnC,IAAI,CAACE,IAAA,IAAQ,CAACC,GAAA,EAAK;YACjB;UACF;UACA;UACA7B,QAAA,CAAS+B,OAAO,CAAC,CAACC,UAAA,EAAYC,SAAA;YAC5B;YACA,MAAMC,UAAA,GAAavC,SAAA,CAAUiC,IAAA,EAAMI,UAAA,CAAW1B,WAAW;YACzD,IAAI,CAAC4B,UAAA,EAAY;cACf,OAAOL,GAAA,CAAIM,OAAO,CAACF,SAAA,CAAU;cAC7BJ,GAAA,CAAIO,KAAK,CAACC,OAAO,GAAG;cACpB;YACF;YACAR,GAAA,CAAIM,OAAO,CAACF,SAAA,CAAU,GAAGC,UAAA;YACzB,MAAMI,GAAA,GAAMN,UAAA,CAAW3B,WAAW,CAAC6B,UAAA,CAAW,EAAEI,GAAA;YAChD,IAAI,CAACA,GAAA,EAAK;cACR;YACF;YACA7B,MAAA,CAAO8B,OAAO,CAACD,GAAA,EAAKP,OAAO,CAAC,CAAC,CAACS,GAAA,EAAKhC,KAAA,CAAM;cACvCqB,GAAA,CAAIO,KAAK,CAACK,WAAW,CAACD,GAAA,EAAKhC,KAAA;YAC7B;UACF;QACF;MACF;IACF;EACF,GAAG,CAACO,MAAA,CAAO;EAEX,OAAO;AACT","ignoreList":[]}
|