@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.
Files changed (34) hide show
  1. package/dist/exports/client/bundled.css +1 -1
  2. package/dist/exports/client/index.d.ts +1 -0
  3. package/dist/exports/client/index.d.ts.map +1 -1
  4. package/dist/exports/client/index.js +10 -10
  5. package/dist/exports/client/index.js.map +4 -4
  6. package/dist/features/experimental_table/client/utils/debounce.d.ts +4 -4
  7. package/dist/features/experimental_table/client/utils/debounce.js +4 -4
  8. package/dist/features/experimental_table/client/utils/debounce.js.map +1 -1
  9. package/dist/features/textState/defaultColors.d.ts +91 -0
  10. package/dist/features/textState/defaultColors.d.ts.map +1 -0
  11. package/dist/features/textState/defaultColors.js +386 -0
  12. package/dist/features/textState/defaultColors.js.map +1 -0
  13. package/dist/features/textState/feature.client.d.ts +3 -0
  14. package/dist/features/textState/feature.client.d.ts.map +1 -0
  15. package/dist/features/textState/feature.client.js +69 -0
  16. package/dist/features/textState/feature.client.js.map +1 -0
  17. package/dist/features/textState/feature.server.d.ts +60 -0
  18. package/dist/features/textState/feature.server.d.ts.map +1 -0
  19. package/dist/features/textState/feature.server.js +25 -0
  20. package/dist/features/textState/feature.server.js.map +1 -0
  21. package/dist/features/textState/textState.d.ts +6 -0
  22. package/dist/features/textState/textState.d.ts.map +1 -0
  23. package/dist/features/textState/textState.js +67 -0
  24. package/dist/features/textState/textState.js.map +1 -0
  25. package/dist/field/bundled.css +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +2 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/lexical/ui/icons/TextState/index.d.ts +5 -0
  31. package/dist/lexical/ui/icons/TextState/index.d.ts.map +1 -0
  32. package/dist/lexical/ui/icons/TextState/index.js +23 -0
  33. package/dist/lexical/ui/icons/TextState/index.js.map +1 -0
  34. 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":[]}