@haklex/rich-ext-poll 0.5.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 (44) hide show
  1. package/README.md +69 -0
  2. package/dist/PollDataContext.d.ts +11 -0
  3. package/dist/PollDataContext.d.ts.map +1 -0
  4. package/dist/PollEditDecorator.d.ts +13 -0
  5. package/dist/PollEditDecorator.d.ts.map +1 -0
  6. package/dist/PollNode-Cd9E_bOt.js +186 -0
  7. package/dist/PollRenderer.d.ts +3 -0
  8. package/dist/PollRenderer.d.ts.map +1 -0
  9. package/dist/augment.d.ts +9 -0
  10. package/dist/augment.d.ts.map +1 -0
  11. package/dist/edit-CUuz0vB8.js +372 -0
  12. package/dist/edit.d.ts +6 -0
  13. package/dist/edit.d.ts.map +1 -0
  14. package/dist/edit.mjs +2 -0
  15. package/dist/extractPolls.d.ts +4 -0
  16. package/dist/extractPolls.d.ts.map +1 -0
  17. package/dist/index.d.ts +4 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.mjs +5 -0
  20. package/dist/node-D-hnG4zJ.js +47 -0
  21. package/dist/node.d.ts +8 -0
  22. package/dist/node.d.ts.map +1 -0
  23. package/dist/node.mjs +3 -0
  24. package/dist/nodes/PollEditNode.d.ts +14 -0
  25. package/dist/nodes/PollEditNode.d.ts.map +1 -0
  26. package/dist/nodes/PollNode.d.ts +52 -0
  27. package/dist/nodes/PollNode.d.ts.map +1 -0
  28. package/dist/poll-edit.css.d.ts +43 -0
  29. package/dist/poll-edit.css.d.ts.map +1 -0
  30. package/dist/poll.css.d.ts +43 -0
  31. package/dist/poll.css.d.ts.map +1 -0
  32. package/dist/renderer-CJEY_O80.js +257 -0
  33. package/dist/renderer.d.ts +8 -0
  34. package/dist/renderer.d.ts.map +1 -0
  35. package/dist/renderer.mjs +2 -0
  36. package/dist/rich-ext-poll.css +2 -0
  37. package/dist/slot.d.ts +8 -0
  38. package/dist/slot.d.ts.map +1 -0
  39. package/dist/static.d.ts +3 -0
  40. package/dist/static.d.ts.map +1 -0
  41. package/dist/static.mjs +4 -0
  42. package/dist/types.d.ts +36 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/package.json +72 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @haklex/rich-ext-poll
2
+
3
+ Reader-facing vote/poll widget extension. Single- or multi-choice polls with optional close time and result-visibility policy.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @haklex/rich-ext-poll
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Register nodes
14
+
15
+ Editor (read + write):
16
+
17
+ ```ts
18
+ import { pollEditNodes } from '@haklex/rich-ext-poll'
19
+
20
+ const editorConfig = { nodes: [...pollEditNodes] }
21
+ ```
22
+
23
+ Static / read-only:
24
+
25
+ ```ts
26
+ import { pollNodes } from '@haklex/rich-ext-poll/static'
27
+
28
+ const staticConfig = { nodes: [...pollNodes] }
29
+ ```
30
+
31
+ ### Provide a data adapter
32
+
33
+ The renderer reads tallies and submits votes through a `PollDataAdapter`. Wrap the renderer with `PollDataProvider`:
34
+
35
+ ```tsx
36
+ import { PollDataProvider } from '@haklex/rich-ext-poll'
37
+
38
+ <PollDataProvider adapter={myAdapter} initialStates={initial}>
39
+ <RichRenderer value={state} />
40
+ </PollDataProvider>
41
+ ```
42
+
43
+ Without an adapter the renderer falls back to a static read-only display.
44
+
45
+ ### Extract poll metadata for SSR
46
+
47
+ ```ts
48
+ import { extractPolls } from '@haklex/rich-ext-poll/static'
49
+
50
+ const polls = extractPolls(serializedEditorState)
51
+ ```
52
+
53
+ ### Stylesheet
54
+
55
+ ```ts
56
+ import '@haklex/rich-ext-poll/style.css'
57
+ ```
58
+
59
+ ## Sub-path Exports
60
+
61
+ | Path | Description |
62
+ | --- | --- |
63
+ | `@haklex/rich-ext-poll` | Full exports (edit + static) |
64
+ | `@haklex/rich-ext-poll/static` | Static-only (no editor UI deps) |
65
+ | `@haklex/rich-ext-poll/style.css` | Stylesheet |
66
+
67
+ ## License
68
+
69
+ MIT
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+ import { PollDataAdapter, PollState } from './types';
3
+ export interface PollDataProviderProps {
4
+ adapter: PollDataAdapter;
5
+ children: ReactNode;
6
+ initialStates?: Record<string, PollState>;
7
+ }
8
+ export declare function PollDataProvider({ adapter, initialStates, children }: PollDataProviderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function usePollDataAdapter(): PollDataAdapter | null;
10
+ export declare function useInitialPollState(pollId: string): PollState | undefined;
11
+ //# sourceMappingURL=PollDataContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PollDataContext.d.ts","sourceRoot":"","sources":["../src/PollDataContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAY1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAM3F;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAE3D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEzE"}
@@ -0,0 +1,13 @@
1
+ import { PollMode, PollOption, PollShowResults } from './types';
2
+ interface PollEditDecoratorProps {
3
+ closeAt?: string;
4
+ mode: PollMode;
5
+ nodeKey: string;
6
+ options: PollOption[];
7
+ pollId: string;
8
+ question: string;
9
+ showResults?: PollShowResults;
10
+ }
11
+ export declare function PollEditDecorator({ closeAt, mode, nodeKey, options, pollId, question, showResults, }: PollEditDecoratorProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=PollEditDecorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PollEditDecorator.d.ts","sourceRoot":"","sources":["../src/PollEditDecorator.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAUrE,UAAU,sBAAsB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AA8DD,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EACJ,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,EACR,WAAW,GACZ,EAAE,sBAAsB,2CAiNxB"}
@@ -0,0 +1,186 @@
1
+ import { DecoratorNode } from "lexical";
2
+ import { customAlphabet } from "nanoid";
3
+ import { createRendererDecoration } from "@haklex/rich-editor/renderers";
4
+ //#region src/slot.ts
5
+ /**
6
+ * RendererConfig slot key for `@haklex/rich-ext-poll`.
7
+ *
8
+ * Override modules should reference this constant instead of the bare string
9
+ * literal so renames stay searchable across the workspace.
10
+ */
11
+ var POLL_NODE_KEY = "Poll";
12
+ //#endregion
13
+ //#region \0@oxc-project+runtime@0.127.0/helpers/typeof.js
14
+ function _typeof(o) {
15
+ "@babel/helpers - typeof";
16
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
17
+ return typeof o;
18
+ } : function(o) {
19
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
20
+ }, _typeof(o);
21
+ }
22
+ //#endregion
23
+ //#region \0@oxc-project+runtime@0.127.0/helpers/toPrimitive.js
24
+ function toPrimitive(t, r) {
25
+ if ("object" != _typeof(t) || !t) return t;
26
+ var e = t[Symbol.toPrimitive];
27
+ if (void 0 !== e) {
28
+ var i = e.call(t, r || "default");
29
+ if ("object" != _typeof(i)) return i;
30
+ throw new TypeError("@@toPrimitive must return a primitive value.");
31
+ }
32
+ return ("string" === r ? String : Number)(t);
33
+ }
34
+ //#endregion
35
+ //#region \0@oxc-project+runtime@0.127.0/helpers/toPropertyKey.js
36
+ function toPropertyKey(t) {
37
+ var i = toPrimitive(t, "string");
38
+ return "symbol" == _typeof(i) ? i : i + "";
39
+ }
40
+ //#endregion
41
+ //#region \0@oxc-project+runtime@0.127.0/helpers/defineProperty.js
42
+ function _defineProperty(e, r, t) {
43
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
44
+ value: t,
45
+ enumerable: !0,
46
+ configurable: !0,
47
+ writable: !0
48
+ }) : e[r] = t, e;
49
+ }
50
+ //#endregion
51
+ //#region src/nodes/PollNode.ts
52
+ var idAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
53
+ var makePollIdSuffix = customAlphabet(idAlphabet, 10);
54
+ var makeOptionIdSuffix = customAlphabet(idAlphabet, 6);
55
+ function createPollId() {
56
+ return `p_${makePollIdSuffix()}`;
57
+ }
58
+ function createOptionId() {
59
+ return `o_${makeOptionIdSuffix()}`;
60
+ }
61
+ var PollNode = class PollNode extends DecoratorNode {
62
+ static getType() {
63
+ return "poll";
64
+ }
65
+ static clone(node) {
66
+ return new PollNode({
67
+ pollId: node.__pollId,
68
+ question: node.__question,
69
+ options: node.__options,
70
+ mode: node.__mode,
71
+ closeAt: node.__closeAt,
72
+ showResults: node.__showResults
73
+ }, node.__key);
74
+ }
75
+ constructor(payload = {}, key) {
76
+ super(key);
77
+ _defineProperty(this, "__pollId", void 0);
78
+ _defineProperty(this, "__question", void 0);
79
+ _defineProperty(this, "__options", void 0);
80
+ _defineProperty(this, "__mode", void 0);
81
+ _defineProperty(this, "__closeAt", void 0);
82
+ _defineProperty(this, "__showResults", void 0);
83
+ this.__pollId = payload.pollId ?? createPollId();
84
+ this.__question = payload.question ?? "";
85
+ this.__options = payload.options && payload.options.length > 0 ? payload.options : [{
86
+ id: createOptionId(),
87
+ label: ""
88
+ }, {
89
+ id: createOptionId(),
90
+ label: ""
91
+ }];
92
+ this.__mode = payload.mode ?? "single";
93
+ this.__closeAt = payload.closeAt;
94
+ this.__showResults = payload.showResults;
95
+ }
96
+ createDOM(_config) {
97
+ const div = document.createElement("div");
98
+ div.className = "rich-poll-wrapper";
99
+ return div;
100
+ }
101
+ updateDOM() {
102
+ return false;
103
+ }
104
+ isInline() {
105
+ return false;
106
+ }
107
+ getPollId() {
108
+ return this.getLatest().__pollId;
109
+ }
110
+ getQuestion() {
111
+ return this.getLatest().__question;
112
+ }
113
+ setQuestion(question) {
114
+ const writable = this.getWritable();
115
+ writable.__question = question;
116
+ }
117
+ getOptions() {
118
+ return this.getLatest().__options;
119
+ }
120
+ setOptions(options) {
121
+ const writable = this.getWritable();
122
+ writable.__options = options;
123
+ }
124
+ getMode() {
125
+ return this.getLatest().__mode;
126
+ }
127
+ setMode(mode) {
128
+ const writable = this.getWritable();
129
+ writable.__mode = mode;
130
+ }
131
+ getCloseAt() {
132
+ return this.getLatest().__closeAt;
133
+ }
134
+ setCloseAt(closeAt) {
135
+ const writable = this.getWritable();
136
+ writable.__closeAt = closeAt;
137
+ }
138
+ getShowResults() {
139
+ return this.getLatest().__showResults;
140
+ }
141
+ setShowResults(showResults) {
142
+ const writable = this.getWritable();
143
+ writable.__showResults = showResults;
144
+ }
145
+ static importJSON(serializedNode) {
146
+ return new PollNode({
147
+ pollId: serializedNode.pollId,
148
+ question: serializedNode.question,
149
+ options: serializedNode.options,
150
+ mode: serializedNode.mode,
151
+ closeAt: serializedNode.closeAt,
152
+ showResults: serializedNode.showResults
153
+ });
154
+ }
155
+ exportJSON() {
156
+ return {
157
+ ...super.exportJSON(),
158
+ type: "poll",
159
+ pollId: this.__pollId,
160
+ question: this.__question,
161
+ options: this.__options,
162
+ mode: this.__mode,
163
+ ...this.__closeAt ? { closeAt: this.__closeAt } : {},
164
+ ...this.__showResults ? { showResults: this.__showResults } : {},
165
+ version: 1
166
+ };
167
+ }
168
+ decorate(_editor, _config) {
169
+ return createRendererDecoration(POLL_NODE_KEY, void 0, {
170
+ pollId: this.__pollId,
171
+ question: this.__question,
172
+ options: this.__options,
173
+ mode: this.__mode,
174
+ closeAt: this.__closeAt,
175
+ showResults: this.__showResults
176
+ });
177
+ }
178
+ };
179
+ function $createPollNode(payload) {
180
+ return new PollNode(payload);
181
+ }
182
+ function $isPollNode(node) {
183
+ return node instanceof PollNode;
184
+ }
185
+ //#endregion
186
+ export { createPollId as a, createOptionId as i, $isPollNode as n, _defineProperty as o, PollNode as r, POLL_NODE_KEY as s, $createPollNode as t };
@@ -0,0 +1,3 @@
1
+ import { PollRendererProps } from './types';
2
+ export declare function PollRenderer(props: PollRendererProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=PollRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PollRenderer.d.ts","sourceRoot":"","sources":["../src/PollRenderer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,iBAAiB,EAGlB,MAAM,SAAS,CAAC;AAgPjB,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,2CAIpD"}
@@ -0,0 +1,9 @@
1
+ import { ComponentType } from 'react';
2
+ import { PollRendererProps } from './types';
3
+ declare module '@haklex/rich-editor' {
4
+ interface RendererConfig {
5
+ Poll?: ComponentType<PollRendererProps>;
6
+ }
7
+ }
8
+ export {};
9
+ //# sourceMappingURL=augment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"augment.d.ts","sourceRoot":"","sources":["../src/augment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,cAAc;QACtB,IAAI,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;KACzC;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,372 @@
1
+ /* empty css */
2
+ import { n as $isPollNode, o as _defineProperty, r as PollNode } from "./PollNode-Cd9E_bOt.js";
3
+ import { $getNodeByKey, $insertNodes } from "lexical";
4
+ import { CalendarClock, ChevronDown, ChevronUp, Plus, Vote, X } from "lucide-react";
5
+ import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
6
+ import { SegmentedControl, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@haklex/rich-editor-ui";
7
+ import { customAlphabet } from "nanoid";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/poll-edit.css.ts
10
+ var pollEditClasses = {
11
+ container: "jr1ls70",
12
+ meta: "jr1ls71",
13
+ question: "jr1ls72",
14
+ optionList: "jr1ls73",
15
+ optionRow: "jr1ls74",
16
+ reorderColumn: "jr1ls75",
17
+ reorderButton: "jr1ls76",
18
+ optionInput: "jr1ls77",
19
+ removeButton: "jr1ls78",
20
+ addOption: "jr1ls79",
21
+ advancedSummary: "jr1ls7a",
22
+ advancedGrid: "jr1ls7b",
23
+ advancedLabel: "jr1ls7c",
24
+ dateTimeField: "jr1ls7d",
25
+ dateTimeIcon: "jr1ls7e",
26
+ dateTimeInput: "jr1ls7f",
27
+ selectTrigger: "jr1ls7g",
28
+ selectContent: "jr1ls7h",
29
+ modeRow: "jr1ls7i",
30
+ modeControl: "jr1ls7j"
31
+ };
32
+ //#endregion
33
+ //#region ../../node_modules/.pnpm/@lexical+react@0.44.0_react-dom@19.2.5_react@19.2.5__react@19.2.5_yjs@13.6.29/node_modules/@lexical/react/LexicalComposerContext.prod.mjs
34
+ /**
35
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
36
+ *
37
+ * This source code is licensed under the MIT license found in the
38
+ * LICENSE file in the root directory of this source tree.
39
+ *
40
+ */
41
+ var r = createContext(null);
42
+ function o() {
43
+ const n = useContext(r);
44
+ return n ?? function(n, ...e) {
45
+ const r = new URL("https://lexical.dev/docs/error"), t = new URLSearchParams();
46
+ t.append("code", n);
47
+ for (const n of e) t.append("v", n);
48
+ throw r.search = t.toString(), Error(`Minified Lexical error #${n}; visit ${r.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`);
49
+ }(8), n;
50
+ }
51
+ //#endregion
52
+ //#region src/PollEditDecorator.tsx
53
+ var makeOptionId = customAlphabet("abcdefghijklmnopqrstuvwxyz0123456789", 6);
54
+ var pollModeItems = [{
55
+ label: "Single",
56
+ value: "single"
57
+ }, {
58
+ label: "Multiple",
59
+ value: "multiple"
60
+ }];
61
+ function moveItem(arr, from, to) {
62
+ if (to < 0 || to >= arr.length) return arr;
63
+ const next = arr.slice();
64
+ const [item] = next.splice(from, 1);
65
+ next.splice(to, 0, item);
66
+ return next;
67
+ }
68
+ function ImeSafeInput({ value, onValueChange, onCompositionEnd, ...rest }) {
69
+ const [local, setLocal] = useState(value);
70
+ const composingRef = useRef(false);
71
+ const lastCommittedRef = useRef(value);
72
+ useEffect(() => {
73
+ if (composingRef.current) return;
74
+ if (value !== lastCommittedRef.current) {
75
+ lastCommittedRef.current = value;
76
+ setLocal(value);
77
+ }
78
+ }, [value]);
79
+ const commit = useCallback((next) => {
80
+ lastCommittedRef.current = next;
81
+ if (next !== value) onValueChange(next);
82
+ }, [onValueChange, value]);
83
+ return /* @__PURE__ */ jsx("input", {
84
+ ...rest,
85
+ value: local,
86
+ onChange: (event) => {
87
+ const next = event.target.value;
88
+ setLocal(next);
89
+ if (!composingRef.current) commit(next);
90
+ },
91
+ onCompositionEnd: (event) => {
92
+ composingRef.current = false;
93
+ const next = event.currentTarget.value;
94
+ setLocal(next);
95
+ commit(next);
96
+ onCompositionEnd?.(event);
97
+ },
98
+ onCompositionStart: () => {
99
+ composingRef.current = true;
100
+ }
101
+ });
102
+ }
103
+ function PollEditDecorator({ closeAt, mode, nodeKey, options, pollId, question, showResults }) {
104
+ const [editor] = o();
105
+ const editable = editor.isEditable();
106
+ const updatePoll = useCallback((mutate) => {
107
+ editor.update(() => {
108
+ const node = $getNodeByKey(nodeKey);
109
+ if ($isPollNode(node)) mutate(node);
110
+ });
111
+ }, [editor, nodeKey]);
112
+ const handleQuestionChange = useCallback((value) => {
113
+ updatePoll((node) => node.setQuestion(value));
114
+ }, [updatePoll]);
115
+ const handleOptionLabelChange = useCallback((id, label) => {
116
+ updatePoll((node) => node.setOptions(node.getOptions().map((o) => o.id === id ? {
117
+ ...o,
118
+ label
119
+ } : o)));
120
+ }, [updatePoll]);
121
+ const handleOptionRemove = useCallback((id) => {
122
+ updatePoll((node) => node.setOptions(node.getOptions().filter((o) => o.id !== id)));
123
+ }, [updatePoll]);
124
+ const handleOptionAdd = useCallback(() => {
125
+ updatePoll((node) => node.setOptions([...node.getOptions(), {
126
+ id: `o_${makeOptionId()}`,
127
+ label: ""
128
+ }]));
129
+ }, [updatePoll]);
130
+ const handleOptionMove = useCallback((index, direction) => {
131
+ updatePoll((node) => {
132
+ const current = node.getOptions();
133
+ const next = moveItem(current, index, index + direction);
134
+ if (next !== current) node.setOptions(next);
135
+ });
136
+ }, [updatePoll]);
137
+ const handleModeChange = useCallback((next) => {
138
+ updatePoll((node) => node.setMode(next));
139
+ }, [updatePoll]);
140
+ const handleCloseAtChange = useCallback((value) => {
141
+ updatePoll((node) => node.setCloseAt(value || void 0));
142
+ }, [updatePoll]);
143
+ const handleShowResultsChange = useCallback((value) => {
144
+ updatePoll((node) => {
145
+ if (value === "always" || value === "after-vote" || value === "after-close") node.setShowResults(value);
146
+ else node.setShowResults(void 0);
147
+ });
148
+ }, [updatePoll]);
149
+ const handleShowResultsSelectChange = useCallback((value) => {
150
+ if (typeof value === "string") handleShowResultsChange(value);
151
+ }, [handleShowResultsChange]);
152
+ const handleOptionKeyDown = useCallback((event, index) => {
153
+ if (event.key === "Enter") {
154
+ event.preventDefault();
155
+ if (index === options.length - 1) handleOptionAdd();
156
+ }
157
+ }, [handleOptionAdd, options.length]);
158
+ return /* @__PURE__ */ jsxs("div", {
159
+ className: pollEditClasses.container,
160
+ "data-poll-id": pollId,
161
+ children: [
162
+ /* @__PURE__ */ jsxs("div", {
163
+ className: pollEditClasses.meta,
164
+ children: ["Poll · ", mode === "single" ? "Single choice" : "Multiple choice"]
165
+ }),
166
+ /* @__PURE__ */ jsx(ImeSafeInput, {
167
+ "aria-label": "Poll question",
168
+ className: pollEditClasses.question,
169
+ disabled: !editable,
170
+ placeholder: "Question",
171
+ value: question,
172
+ onValueChange: handleQuestionChange
173
+ }),
174
+ /* @__PURE__ */ jsx("ul", {
175
+ className: pollEditClasses.optionList,
176
+ children: options.map((option, index) => /* @__PURE__ */ jsxs("li", {
177
+ className: pollEditClasses.optionRow,
178
+ children: [
179
+ editable && options.length > 1 && /* @__PURE__ */ jsxs("span", {
180
+ className: pollEditClasses.reorderColumn,
181
+ children: [/* @__PURE__ */ jsx("button", {
182
+ "aria-label": "Move option up",
183
+ className: pollEditClasses.reorderButton,
184
+ disabled: index === 0,
185
+ type: "button",
186
+ onClick: () => handleOptionMove(index, -1),
187
+ children: /* @__PURE__ */ jsx(ChevronUp, {
188
+ "aria-hidden": true,
189
+ size: 14
190
+ })
191
+ }), /* @__PURE__ */ jsx("button", {
192
+ "aria-label": "Move option down",
193
+ className: pollEditClasses.reorderButton,
194
+ disabled: index === options.length - 1,
195
+ type: "button",
196
+ onClick: () => handleOptionMove(index, 1),
197
+ children: /* @__PURE__ */ jsx(ChevronDown, {
198
+ "aria-hidden": true,
199
+ size: 14
200
+ })
201
+ })]
202
+ }),
203
+ /* @__PURE__ */ jsx(ImeSafeInput, {
204
+ "aria-label": "Option label",
205
+ className: pollEditClasses.optionInput,
206
+ disabled: !editable,
207
+ placeholder: "Option",
208
+ value: option.label,
209
+ onKeyDown: (event) => handleOptionKeyDown(event, index),
210
+ onValueChange: (next) => handleOptionLabelChange(option.id, next)
211
+ }),
212
+ editable && options.length > 2 && /* @__PURE__ */ jsx("button", {
213
+ "aria-label": "Remove option",
214
+ className: pollEditClasses.removeButton,
215
+ type: "button",
216
+ onClick: () => handleOptionRemove(option.id),
217
+ children: /* @__PURE__ */ jsx(X, {
218
+ "aria-hidden": true,
219
+ size: 16
220
+ })
221
+ })
222
+ ]
223
+ }, option.id))
224
+ }),
225
+ editable && /* @__PURE__ */ jsxs("button", {
226
+ className: pollEditClasses.addOption,
227
+ type: "button",
228
+ onClick: handleOptionAdd,
229
+ children: [/* @__PURE__ */ jsx(Plus, {
230
+ "aria-hidden": true,
231
+ size: 16
232
+ }), /* @__PURE__ */ jsx("span", { children: "Add option" })]
233
+ }),
234
+ editable && /* @__PURE__ */ jsxs("div", {
235
+ className: pollEditClasses.modeRow,
236
+ children: [/* @__PURE__ */ jsx("span", {
237
+ className: pollEditClasses.advancedLabel,
238
+ children: "Mode"
239
+ }), /* @__PURE__ */ jsx(SegmentedControl, {
240
+ className: pollEditClasses.modeControl,
241
+ items: pollModeItems,
242
+ value: mode,
243
+ onChange: handleModeChange
244
+ })]
245
+ }),
246
+ editable && /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx("summary", {
247
+ className: pollEditClasses.advancedSummary,
248
+ children: "Advanced"
249
+ }), /* @__PURE__ */ jsxs("div", {
250
+ className: pollEditClasses.advancedGrid,
251
+ children: [
252
+ /* @__PURE__ */ jsx("span", {
253
+ className: pollEditClasses.advancedLabel,
254
+ children: "Close at"
255
+ }),
256
+ /* @__PURE__ */ jsxs("div", {
257
+ className: pollEditClasses.dateTimeField,
258
+ children: [/* @__PURE__ */ jsx(CalendarClock, {
259
+ "aria-hidden": true,
260
+ className: pollEditClasses.dateTimeIcon,
261
+ size: 16
262
+ }), /* @__PURE__ */ jsx("input", {
263
+ "aria-label": "Closing time",
264
+ className: pollEditClasses.dateTimeInput,
265
+ type: "datetime-local",
266
+ value: closeAt ?? "",
267
+ onChange: (event) => handleCloseAtChange(event.target.value)
268
+ })]
269
+ }),
270
+ /* @__PURE__ */ jsx("span", {
271
+ className: pollEditClasses.advancedLabel,
272
+ children: "Show results"
273
+ }),
274
+ /* @__PURE__ */ jsxs(Select, {
275
+ value: showResults ?? "always",
276
+ onValueChange: handleShowResultsSelectChange,
277
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
278
+ "aria-label": "Show results policy",
279
+ className: pollEditClasses.selectTrigger,
280
+ children: /* @__PURE__ */ jsx(SelectValue, {})
281
+ }), /* @__PURE__ */ jsxs(SelectContent, {
282
+ className: pollEditClasses.selectContent,
283
+ sideOffset: 6,
284
+ children: [
285
+ /* @__PURE__ */ jsx(SelectItem, {
286
+ value: "always",
287
+ children: "Always"
288
+ }),
289
+ /* @__PURE__ */ jsx(SelectItem, {
290
+ value: "after-vote",
291
+ children: "After vote"
292
+ }),
293
+ /* @__PURE__ */ jsx(SelectItem, {
294
+ value: "after-close",
295
+ children: "After close"
296
+ })
297
+ ]
298
+ })]
299
+ })
300
+ ]
301
+ })] })
302
+ ]
303
+ });
304
+ }
305
+ //#endregion
306
+ //#region src/nodes/PollEditNode.ts
307
+ var PollEditNode = class PollEditNode extends PollNode {
308
+ static getType() {
309
+ return "poll";
310
+ }
311
+ static clone(node) {
312
+ return new PollEditNode({
313
+ pollId: node.__pollId,
314
+ question: node.__question,
315
+ options: node.__options,
316
+ mode: node.__mode,
317
+ closeAt: node.__closeAt,
318
+ showResults: node.__showResults
319
+ }, node.__key);
320
+ }
321
+ constructor(payload, key) {
322
+ super(payload, key);
323
+ }
324
+ static importJSON(serializedNode) {
325
+ return new PollEditNode({
326
+ pollId: serializedNode.pollId,
327
+ question: serializedNode.question,
328
+ options: serializedNode.options,
329
+ mode: serializedNode.mode,
330
+ closeAt: serializedNode.closeAt,
331
+ showResults: serializedNode.showResults
332
+ });
333
+ }
334
+ decorate(_editor, _config) {
335
+ return createElement(PollEditDecorator, {
336
+ nodeKey: this.__key,
337
+ pollId: this.__pollId,
338
+ question: this.__question,
339
+ options: this.__options,
340
+ mode: this.__mode,
341
+ closeAt: this.__closeAt,
342
+ showResults: this.__showResults
343
+ });
344
+ }
345
+ };
346
+ _defineProperty(PollEditNode, "commandItems", [{
347
+ title: "Poll",
348
+ icon: createElement(Vote, { size: 20 }),
349
+ description: "Reader-facing vote widget",
350
+ keywords: [
351
+ "poll",
352
+ "vote",
353
+ "survey",
354
+ "choice"
355
+ ],
356
+ section: "ADVANCED",
357
+ placement: ["slash", "toolbar"],
358
+ group: "insert",
359
+ onSelect: (editor) => {
360
+ editor.update(() => {
361
+ $insertNodes([$createPollEditNode()]);
362
+ });
363
+ }
364
+ }]);
365
+ function $createPollEditNode(payload) {
366
+ return new PollEditNode(payload);
367
+ }
368
+ //#endregion
369
+ //#region src/edit.ts
370
+ var pollEditNodes = [PollEditNode];
371
+ //#endregion
372
+ export { pollEditClasses as a, PollEditDecorator as i, $createPollEditNode as n, PollEditNode as r, pollEditNodes as t };
package/dist/edit.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { Klass, LexicalNode } from 'lexical';
2
+ export { $createPollEditNode, PollEditNode } from './nodes/PollEditNode';
3
+ export { pollEditClasses } from './poll-edit.css';
4
+ export { PollEditDecorator } from './PollEditDecorator';
5
+ export declare const pollEditNodes: Array<Klass<LexicalNode>>;
6
+ //# sourceMappingURL=edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../src/edit.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAIlD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAkB,CAAC"}