@studiocms/wysiwyg 0.1.0-experimental.2 → 0.1.0-experimental.3

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 (67) hide show
  1. package/dist/wysiwyg/components/Editor.astro +24 -38
  2. package/dist/wysiwyg/editorPlugins/blocks/blocks.d.ts +3 -0
  3. package/dist/wysiwyg/editorPlugins/blocks/blocks.js +239 -0
  4. package/dist/wysiwyg/editorPlugins/blocks/index.d.ts +80 -0
  5. package/dist/wysiwyg/editorPlugins/blocks/index.js +26 -0
  6. package/dist/wysiwyg/editorPlugins/code/blocks.d.ts +4 -0
  7. package/dist/wysiwyg/editorPlugins/code/blocks.js +20 -0
  8. package/dist/wysiwyg/editorPlugins/code/commands.d.ts +4 -0
  9. package/dist/wysiwyg/editorPlugins/code/commands.js +109 -0
  10. package/dist/wysiwyg/editorPlugins/code/components.d.ts +4 -0
  11. package/dist/wysiwyg/editorPlugins/code/components.js +88 -0
  12. package/dist/wysiwyg/editorPlugins/code/index.d.ts +47 -0
  13. package/dist/wysiwyg/editorPlugins/code/index.js +28 -0
  14. package/dist/wysiwyg/editorPlugins/code/utils.d.ts +3 -0
  15. package/dist/wysiwyg/editorPlugins/code/utils.js +8 -0
  16. package/dist/wysiwyg/editorPlugins/countdown.d.ts +86 -0
  17. package/dist/wysiwyg/editorPlugins/countdown.js +163 -0
  18. package/dist/wysiwyg/editorPlugins/forms/blocks.d.ts +3 -0
  19. package/dist/wysiwyg/editorPlugins/forms/blocks.js +93 -0
  20. package/dist/wysiwyg/editorPlugins/forms/components.d.ts +11 -0
  21. package/dist/wysiwyg/editorPlugins/forms/components.js +284 -0
  22. package/dist/wysiwyg/editorPlugins/forms/index.d.ts +21 -0
  23. package/dist/wysiwyg/editorPlugins/forms/index.js +18 -0
  24. package/dist/wysiwyg/editorPlugins/forms/traits.d.ts +2 -0
  25. package/dist/wysiwyg/editorPlugins/forms/traits.js +47 -0
  26. package/dist/wysiwyg/editorPlugins/index.d.ts +9 -0
  27. package/dist/wysiwyg/editorPlugins/index.js +20 -0
  28. package/dist/wysiwyg/editorPlugins/rte/colorPicker.d.ts +95 -0
  29. package/dist/wysiwyg/editorPlugins/rte/colorPicker.js +185 -0
  30. package/dist/wysiwyg/editorPlugins/rte/index.d.ts +48 -0
  31. package/dist/wysiwyg/editorPlugins/rte/index.js +369 -0
  32. package/dist/wysiwyg/editorPlugins/rte/styles.css +63 -0
  33. package/dist/wysiwyg/editorPlugins/tabs/blocks.d.ts +3 -0
  34. package/dist/wysiwyg/editorPlugins/tabs/blocks.js +19 -0
  35. package/dist/wysiwyg/editorPlugins/tabs/components/Tab.d.ts +10 -0
  36. package/dist/wysiwyg/editorPlugins/tabs/components/Tab.js +100 -0
  37. package/dist/wysiwyg/editorPlugins/tabs/components/TabContainer.d.ts +5 -0
  38. package/dist/wysiwyg/editorPlugins/tabs/components/TabContainer.js +23 -0
  39. package/dist/wysiwyg/editorPlugins/tabs/components/TabContent.d.ts +5 -0
  40. package/dist/wysiwyg/editorPlugins/tabs/components/TabContent.js +23 -0
  41. package/dist/wysiwyg/editorPlugins/tabs/components/TabContents.d.ts +4 -0
  42. package/dist/wysiwyg/editorPlugins/tabs/components/TabContents.js +19 -0
  43. package/dist/wysiwyg/editorPlugins/tabs/components/Tabs.d.ts +4 -0
  44. package/dist/wysiwyg/editorPlugins/tabs/components/Tabs.js +169 -0
  45. package/dist/wysiwyg/editorPlugins/tabs/components/index.d.ts +4 -0
  46. package/dist/wysiwyg/editorPlugins/tabs/components/index.js +29 -0
  47. package/dist/wysiwyg/editorPlugins/tabs/index.d.ts +5 -0
  48. package/dist/wysiwyg/editorPlugins/tabs/index.js +15 -0
  49. package/dist/wysiwyg/editorPlugins/tabs/options.d.ts +5 -0
  50. package/dist/wysiwyg/editorPlugins/tabs/options.js +80 -0
  51. package/dist/wysiwyg/editorPlugins/tabs/types.d.ts +81 -0
  52. package/dist/wysiwyg/editorPlugins/tabs/types.js +0 -0
  53. package/dist/wysiwyg/editorPlugins/tooltip.d.ts +68 -0
  54. package/dist/wysiwyg/editorPlugins/tooltip.js +318 -0
  55. package/dist/wysiwyg/editorPlugins/tuiImageEditor.d.ts +86 -0
  56. package/dist/wysiwyg/editorPlugins/tuiImageEditor.js +204 -0
  57. package/dist/wysiwyg/editorPlugins/typed/blocks.d.ts +4 -0
  58. package/dist/wysiwyg/editorPlugins/typed/blocks.js +15 -0
  59. package/dist/wysiwyg/editorPlugins/typed/components.d.ts +9 -0
  60. package/dist/wysiwyg/editorPlugins/typed/components.js +109 -0
  61. package/dist/wysiwyg/editorPlugins/typed/index.d.ts +35 -0
  62. package/dist/wysiwyg/editorPlugins/typed/index.js +18 -0
  63. package/dist/wysiwyg/editorPlugins/typed/traits.d.ts +3 -0
  64. package/dist/wysiwyg/editorPlugins/typed/traits.js +18 -0
  65. package/dist/wysiwyg/editorPlugins/typed/utils.d.ts +2 -0
  66. package/dist/wysiwyg/editorPlugins/typed/utils.js +6 -0
  67. package/package.json +2 -14
@@ -0,0 +1,284 @@
1
+ const typeForm = "form";
2
+ const typeInput = "input";
3
+ const typeTextarea = "textarea";
4
+ const typeSelect = "select";
5
+ const typeCheckbox = "checkbox";
6
+ const typeRadio = "radio";
7
+ const typeButton = "button";
8
+ const typeLabel = "label";
9
+ const typeOption = "option";
10
+ function components_default(editor) {
11
+ const { Components } = editor;
12
+ const idTrait = {
13
+ name: "id"
14
+ };
15
+ const forTrait = {
16
+ name: "for"
17
+ };
18
+ const nameTrait = {
19
+ name: "name"
20
+ };
21
+ const placeholderTrait = {
22
+ name: "placeholder"
23
+ };
24
+ const valueTrait = {
25
+ name: "value"
26
+ };
27
+ const requiredTrait = {
28
+ type: "checkbox",
29
+ name: "required"
30
+ };
31
+ const checkedTrait = {
32
+ type: "checkbox",
33
+ name: "checked"
34
+ };
35
+ const createOption = (value, content) => {
36
+ return { type: typeOption, content, attributes: { value } };
37
+ };
38
+ const checkIfInPreview = (ev) => {
39
+ if (!editor.Commands.isActive("preview")) {
40
+ ev.preventDefault();
41
+ }
42
+ };
43
+ Components.addType(typeForm, {
44
+ isComponent: (el) => el.tagName === "FORM",
45
+ model: {
46
+ defaults: {
47
+ tagName: "form",
48
+ droppable: ":not(form)",
49
+ draggable: ":not(form)",
50
+ attributes: { method: "get" },
51
+ traits: [
52
+ {
53
+ type: "select",
54
+ name: "method",
55
+ options: [
56
+ {
57
+ value: "get",
58
+ name: "GET",
59
+ id: ""
60
+ },
61
+ {
62
+ value: "post",
63
+ name: "POST",
64
+ id: ""
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ name: "action"
70
+ }
71
+ ]
72
+ }
73
+ },
74
+ view: {
75
+ events: {
76
+ // The submit of the form might redirect the user from the editor so
77
+ // we should always prevent the default here.
78
+ submit: (e) => e.preventDefault()
79
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
80
+ }
81
+ }
82
+ });
83
+ Components.addType(typeInput, {
84
+ isComponent: (el) => el.tagName === "INPUT",
85
+ model: {
86
+ defaults: {
87
+ tagName: "input",
88
+ droppable: false,
89
+ highlightable: false,
90
+ attributes: { type: "text" },
91
+ traits: [
92
+ nameTrait,
93
+ placeholderTrait,
94
+ {
95
+ type: "select",
96
+ name: "type",
97
+ options: [
98
+ {
99
+ value: "text",
100
+ id: ""
101
+ },
102
+ {
103
+ value: "email",
104
+ id: ""
105
+ },
106
+ {
107
+ value: "password",
108
+ id: ""
109
+ },
110
+ {
111
+ value: "number",
112
+ id: ""
113
+ }
114
+ ]
115
+ },
116
+ requiredTrait
117
+ ]
118
+ }
119
+ },
120
+ extendFnView: ["updateAttributes"],
121
+ view: {
122
+ updateAttributes() {
123
+ this.el.setAttribute("autocomplete", "off");
124
+ }
125
+ }
126
+ });
127
+ Components.addType(typeTextarea, {
128
+ extend: typeInput,
129
+ isComponent: (el) => el.tagName === "TEXTAREA",
130
+ model: {
131
+ defaults: {
132
+ tagName: "textarea",
133
+ attributes: {},
134
+ traits: [nameTrait, placeholderTrait, requiredTrait]
135
+ }
136
+ }
137
+ });
138
+ Components.addType(typeOption, {
139
+ isComponent: (el) => el.tagName === "OPTION",
140
+ model: {
141
+ defaults: {
142
+ tagName: "option",
143
+ layerable: false,
144
+ droppable: false,
145
+ draggable: false,
146
+ highlightable: false
147
+ }
148
+ }
149
+ });
150
+ Components.addType(typeSelect, {
151
+ isComponent: (el) => el.tagName === "SELECT",
152
+ model: {
153
+ defaults: {
154
+ tagName: "select",
155
+ droppable: false,
156
+ highlightable: false,
157
+ components: [createOption("opt1", "Option 1"), createOption("opt2", "Option 2")],
158
+ traits: [
159
+ nameTrait,
160
+ {
161
+ name: "options",
162
+ type: "select-options"
163
+ },
164
+ requiredTrait
165
+ ]
166
+ }
167
+ },
168
+ view: {
169
+ events: {
170
+ mousedown: checkIfInPreview
171
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
172
+ }
173
+ }
174
+ });
175
+ Components.addType(typeCheckbox, {
176
+ extend: typeInput,
177
+ isComponent: (el) => el.tagName === "INPUT" && el.type === "checkbox",
178
+ model: {
179
+ defaults: {
180
+ copyable: false,
181
+ attributes: { type: "checkbox" },
182
+ traits: [idTrait, nameTrait, valueTrait, requiredTrait, checkedTrait]
183
+ }
184
+ },
185
+ view: {
186
+ events: {
187
+ click: checkIfInPreview
188
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
189
+ },
190
+ init() {
191
+ this.listenTo(this.model, "change:attributes:checked", this.handleChecked);
192
+ },
193
+ handleChecked() {
194
+ this.el.checked = !!this.model.get("attributes")?.checked;
195
+ }
196
+ }
197
+ });
198
+ Components.addType(typeRadio, {
199
+ extend: typeCheckbox,
200
+ isComponent: (el) => el.tagName === "INPUT" && el.type === "radio",
201
+ model: {
202
+ defaults: {
203
+ attributes: { type: "radio" }
204
+ }
205
+ }
206
+ });
207
+ Components.addType(typeButton, {
208
+ extend: typeInput,
209
+ isComponent: (el) => el.tagName === "BUTTON",
210
+ model: {
211
+ defaults: {
212
+ tagName: "button",
213
+ attributes: { type: "button" },
214
+ text: "Send",
215
+ traits: [
216
+ {
217
+ name: "text",
218
+ changeProp: true
219
+ },
220
+ {
221
+ type: "select",
222
+ name: "type",
223
+ options: [
224
+ {
225
+ value: "button",
226
+ id: ""
227
+ },
228
+ {
229
+ value: "submit",
230
+ id: ""
231
+ },
232
+ {
233
+ value: "reset",
234
+ id: ""
235
+ }
236
+ ]
237
+ }
238
+ ]
239
+ },
240
+ init() {
241
+ const comps = this.components();
242
+ const tChild = comps.length === 1 && comps.models[0];
243
+ const chCnt = tChild && tChild.is("textnode") && tChild.get("content") || "";
244
+ const text = chCnt || this.get("text");
245
+ this.set("text", text);
246
+ this.on("change:text", this.__onTextChange);
247
+ text !== chCnt && this.__onTextChange();
248
+ },
249
+ __onTextChange() {
250
+ this.components(this.get("text"));
251
+ }
252
+ },
253
+ view: {
254
+ events: {
255
+ click: checkIfInPreview
256
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
257
+ }
258
+ }
259
+ });
260
+ Components.addType(typeLabel, {
261
+ extend: "text",
262
+ isComponent: (el) => el.tagName === "LABEL",
263
+ model: {
264
+ defaults: {
265
+ tagName: "label",
266
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
267
+ components: "Label",
268
+ traits: [forTrait]
269
+ }
270
+ }
271
+ });
272
+ }
273
+ export {
274
+ components_default as default,
275
+ typeButton,
276
+ typeCheckbox,
277
+ typeForm,
278
+ typeInput,
279
+ typeLabel,
280
+ typeOption,
281
+ typeRadio,
282
+ typeSelect,
283
+ typeTextarea
284
+ };
@@ -0,0 +1,21 @@
1
+ import type { BlockProperties, Plugin } from 'grapesjs';
2
+ export type PluginOptions = {
3
+ /**
4
+ * Which blocks to add.
5
+ * @default ['form', 'input', 'textarea', 'select', 'button', 'label', 'checkbox', 'radio']
6
+ */
7
+ blocks?: string[];
8
+ /**
9
+ * Category name for blocks.
10
+ * @default 'Forms'
11
+ */
12
+ category?: BlockProperties['category'];
13
+ /**
14
+ * Add custom block options, based on block id.
15
+ * @default (blockId) => ({})
16
+ * @example (blockId) => blockId === 'input' ? { attributes: {...} } : {};
17
+ */
18
+ block?: (blockId: string) => {};
19
+ };
20
+ declare const plugin: Plugin<PluginOptions>;
21
+ export default plugin;
@@ -0,0 +1,18 @@
1
+ import loadBlocks from "./blocks.js";
2
+ import loadComponents from "./components.js";
3
+ import loadTraits from "./traits.js";
4
+ const plugin = (editor, opts = {}) => {
5
+ const config = {
6
+ blocks: ["form", "input", "textarea", "select", "button", "label", "checkbox", "radio"],
7
+ category: { id: "forms", label: "Forms" },
8
+ block: () => ({}),
9
+ ...opts
10
+ };
11
+ loadComponents(editor);
12
+ loadTraits(editor);
13
+ loadBlocks(editor, config);
14
+ };
15
+ var forms_default = plugin;
16
+ export {
17
+ forms_default as default
18
+ };
@@ -0,0 +1,2 @@
1
+ import type { Editor } from 'grapesjs';
2
+ export default function (editor: Editor): void;
@@ -0,0 +1,47 @@
1
+ import { typeOption } from "./components.js";
2
+ function traits_default(editor) {
3
+ const trm = editor.TraitManager;
4
+ trm.addType("select-options", {
5
+ events: {
6
+ keyup: "onChange"
7
+ },
8
+ onValueChange() {
9
+ const { model, target } = this;
10
+ const optionsStr = model.get("value").trim();
11
+ const options = optionsStr.split("\n");
12
+ const optComps = [];
13
+ for (let i = 0; i < options.length; i++) {
14
+ const optionStr = options[i];
15
+ const option = optionStr.split("::");
16
+ optComps.push({
17
+ type: typeOption,
18
+ components: option[1] || option[0],
19
+ attributes: { value: option[0] }
20
+ });
21
+ }
22
+ target.components().reset(optComps);
23
+ target.view?.render();
24
+ },
25
+ getInputEl() {
26
+ if (!this.$input) {
27
+ const optionsArr = [];
28
+ const options = this.target.components();
29
+ for (let i = 0; i < options.length; i++) {
30
+ const option = options.models[i];
31
+ const optAttr = option.get("attributes");
32
+ const optValue = optAttr?.value || "";
33
+ const optTxtNode = option.components().models[0];
34
+ const optLabel = optTxtNode?.get("content") || "";
35
+ optionsArr.push(`${optValue}::${optLabel}`);
36
+ }
37
+ const el = document.createElement("textarea");
38
+ el.value = optionsArr.join("\n");
39
+ this.$input = el;
40
+ }
41
+ return this.$input;
42
+ }
43
+ });
44
+ }
45
+ export {
46
+ traits_default as default
47
+ };
@@ -0,0 +1,9 @@
1
+ export { default as blocks } from './blocks/index.js';
2
+ export { default as customCode } from './code/index.js';
3
+ export { default as forms } from './forms/index.js';
4
+ export { default as rte } from './rte/index.js';
5
+ export { default as tabs } from './tabs/index.js';
6
+ export { default as typed } from './typed/index.js';
7
+ export { default as countdown } from './countdown.js';
8
+ export { default as tooltip } from './tooltip.js';
9
+ export { default as tuiImageEditor } from './tuiImageEditor.js';
@@ -0,0 +1,20 @@
1
+ import { default as default2 } from "./blocks/index.js";
2
+ import { default as default3 } from "./code/index.js";
3
+ import { default as default4 } from "./forms/index.js";
4
+ import { default as default5 } from "./rte/index.js";
5
+ import { default as default6 } from "./tabs/index.js";
6
+ import { default as default7 } from "./typed/index.js";
7
+ import { default as default8 } from "./countdown.js";
8
+ import { default as default9 } from "./tooltip.js";
9
+ import { default as default10 } from "./tuiImageEditor.js";
10
+ export {
11
+ default2 as blocks,
12
+ default8 as countdown,
13
+ default3 as customCode,
14
+ default4 as forms,
15
+ default5 as rte,
16
+ default6 as tabs,
17
+ default9 as tooltip,
18
+ default10 as tuiImageEditor,
19
+ default7 as typed
20
+ };
@@ -0,0 +1,95 @@
1
+ interface ColorPickerOptions {
2
+ open?: HTMLElement | string;
3
+ openEvent?: string;
4
+ style?: {
5
+ display?: string;
6
+ [key: string]: string | undefined;
7
+ };
8
+ template?: string;
9
+ autoclose?: boolean;
10
+ closeOnBlur?: boolean;
11
+ }
12
+ export default class ColorPicker {
13
+ private elm;
14
+ private cbs;
15
+ private color;
16
+ private isOpen;
17
+ private colors;
18
+ private options;
19
+ /**
20
+ * ColorPicker
21
+ * Creates a new `ColorPicker` instance.
22
+ *
23
+ * @name ColorPicker
24
+ * @function
25
+ * @param {String|HTMLElement} sel The element where the color picker will live.
26
+ * @param {Array<string>} colors An array of strings representing colors.
27
+ * @param {Object} options An object containing the following fields:
28
+ *
29
+ * - `open` (String|HTMLElement): The HTML element or query selector which will open the picker.
30
+ * - `openEvent` (String): The open event (default: `"click"`).
31
+ * - `style` (Object): Some style options:
32
+ * - `display` (String): The display value when the picker is opened (default: `"block"`).
33
+ * - `template` (String): The color item template. The `{color}` snippet will be replaced
34
+ * with the color value (default: `"<div data-col=\"{color}\" style=\"background-color: {color}\"></div>"`).
35
+ * - `autoclose` (Boolean): If `false`, the color picker will not be hided by default (default: `true`).
36
+ * - `closeOnBlur` (Boolean): If `true`, the color picker will be closed when clicked outside of it (default: `false`).
37
+ *
38
+ * @return {ColorPicker} The `ColorPicker` instance.
39
+ */
40
+ constructor(sel: string | HTMLElement, colors?: string[], options?: ColorPickerOptions);
41
+ /**
42
+ * getElm
43
+ * Finds the HTML element.
44
+ *
45
+ * @name getElm
46
+ * @function
47
+ * @param {String|HTMLElement} el The HTML element or query selector.
48
+ * @return {HTMLElement} The selected HTML element.
49
+ */
50
+ private getElm;
51
+ /**
52
+ * render
53
+ * Renders the colors.
54
+ *
55
+ * @name render
56
+ * @function
57
+ */
58
+ render(): void;
59
+ /**
60
+ * close
61
+ * Closes the color picker.
62
+ *
63
+ * @name close
64
+ * @function
65
+ */
66
+ close(): void;
67
+ /**
68
+ * open
69
+ * Opens the color picker.
70
+ *
71
+ * @name open
72
+ * @function
73
+ */
74
+ open(): void;
75
+ /**
76
+ * colorChosen
77
+ * Adds a new callback in the colorChosen callback buffer.
78
+ *
79
+ * @name colorChosen
80
+ * @function
81
+ * @param {Function} cb The callback function called with the selected color.
82
+ */
83
+ colorChosen(cb: (color: string) => void): void;
84
+ /**
85
+ * set
86
+ * Sets the color picker color.
87
+ *
88
+ * @name set
89
+ * @function
90
+ * @param {String} c The color to set.
91
+ * @param {Boolean} p If `false`, the `colorChosen` callbacks will not be called.
92
+ */
93
+ set(c: string, p?: boolean): void;
94
+ }
95
+ export {};
@@ -0,0 +1,185 @@
1
+ class ColorPicker {
2
+ elm;
3
+ cbs;
4
+ color;
5
+ isOpen;
6
+ colors;
7
+ options;
8
+ /**
9
+ * ColorPicker
10
+ * Creates a new `ColorPicker` instance.
11
+ *
12
+ * @name ColorPicker
13
+ * @function
14
+ * @param {String|HTMLElement} sel The element where the color picker will live.
15
+ * @param {Array<string>} colors An array of strings representing colors.
16
+ * @param {Object} options An object containing the following fields:
17
+ *
18
+ * - `open` (String|HTMLElement): The HTML element or query selector which will open the picker.
19
+ * - `openEvent` (String): The open event (default: `"click"`).
20
+ * - `style` (Object): Some style options:
21
+ * - `display` (String): The display value when the picker is opened (default: `"block"`).
22
+ * - `template` (String): The color item template. The `{color}` snippet will be replaced
23
+ * with the color value (default: `"<div data-col=\"{color}\" style=\"background-color: {color}\"></div>"`).
24
+ * - `autoclose` (Boolean): If `false`, the color picker will not be hided by default (default: `true`).
25
+ * - `closeOnBlur` (Boolean): If `true`, the color picker will be closed when clicked outside of it (default: `false`).
26
+ *
27
+ * @return {ColorPicker} The `ColorPicker` instance.
28
+ */
29
+ constructor(sel, colors, options = {}) {
30
+ const defaultColors = [
31
+ "#1abc9c",
32
+ "#2ecc71",
33
+ "#3498db",
34
+ "#9b59b6",
35
+ "#34495e",
36
+ "#16a085",
37
+ "#27ae60",
38
+ "#2980b9",
39
+ "#8e44ad",
40
+ "#2c3e50",
41
+ "#f1c40f",
42
+ "#e67e22",
43
+ "#e74c3c",
44
+ "#ecf0f1",
45
+ "#95a5a6",
46
+ "#f39c12",
47
+ "#d35400",
48
+ "#c0392b",
49
+ "#bdc3c7",
50
+ "#7f8c8d"
51
+ ];
52
+ this.colors = colors || defaultColors;
53
+ this.options = {
54
+ openEvent: "click",
55
+ style: {
56
+ display: "block"
57
+ },
58
+ closeOnBlur: false,
59
+ template: '<div data-col="{color}" style="background-color: {color}" title="{color}" ></div>',
60
+ autoclose: true,
61
+ ...options
62
+ };
63
+ if (typeof this.options.open === "string") {
64
+ this.options.open = this.getElm(this.options.open);
65
+ }
66
+ this.elm = this.getElm(sel);
67
+ this.cbs = [];
68
+ this.color = "";
69
+ this.isOpen = true;
70
+ this.render();
71
+ if (this.options.open) {
72
+ this.options.open.addEventListener(this.options.openEvent || "click", () => {
73
+ this.isOpen ? this.close() : this.open();
74
+ });
75
+ }
76
+ this.elm.addEventListener("click", (ev) => {
77
+ const target = ev.target;
78
+ const col = target.getAttribute("data-col");
79
+ if (!col) {
80
+ return;
81
+ }
82
+ this.color = col;
83
+ this.set(col);
84
+ this.close();
85
+ });
86
+ if (this.options.closeOnBlur) {
87
+ window.addEventListener("click", (ev) => {
88
+ const target = ev.target;
89
+ if (target !== this.options.open && target !== this.elm && this.isOpen) {
90
+ this.close();
91
+ }
92
+ });
93
+ }
94
+ if (this.options.autoclose !== false) {
95
+ this.close();
96
+ }
97
+ }
98
+ /**
99
+ * getElm
100
+ * Finds the HTML element.
101
+ *
102
+ * @name getElm
103
+ * @function
104
+ * @param {String|HTMLElement} el The HTML element or query selector.
105
+ * @return {HTMLElement} The selected HTML element.
106
+ */
107
+ getElm(el) {
108
+ if (typeof el === "string") {
109
+ const element = document.querySelector(el);
110
+ if (!element) {
111
+ throw new Error(`Element ${el} not found`);
112
+ }
113
+ return element;
114
+ }
115
+ return el;
116
+ }
117
+ /**
118
+ * render
119
+ * Renders the colors.
120
+ *
121
+ * @name render
122
+ * @function
123
+ */
124
+ render() {
125
+ let html = "";
126
+ this.colors.forEach((color) => {
127
+ html += this.options.template?.replace(/\{color\}/g, color) || "";
128
+ });
129
+ this.elm.innerHTML = html;
130
+ }
131
+ /**
132
+ * close
133
+ * Closes the color picker.
134
+ *
135
+ * @name close
136
+ * @function
137
+ */
138
+ close() {
139
+ this.elm.style.display = "none";
140
+ this.isOpen = false;
141
+ }
142
+ /**
143
+ * open
144
+ * Opens the color picker.
145
+ *
146
+ * @name open
147
+ * @function
148
+ */
149
+ open() {
150
+ this.elm.style.display = this.options.style?.display || "block";
151
+ this.isOpen = true;
152
+ }
153
+ /**
154
+ * colorChosen
155
+ * Adds a new callback in the colorChosen callback buffer.
156
+ *
157
+ * @name colorChosen
158
+ * @function
159
+ * @param {Function} cb The callback function called with the selected color.
160
+ */
161
+ colorChosen(cb) {
162
+ this.cbs.push(cb);
163
+ }
164
+ /**
165
+ * set
166
+ * Sets the color picker color.
167
+ *
168
+ * @name set
169
+ * @function
170
+ * @param {String} c The color to set.
171
+ * @param {Boolean} p If `false`, the `colorChosen` callbacks will not be called.
172
+ */
173
+ set(c, p = true) {
174
+ this.color = c;
175
+ if (p === false) {
176
+ return;
177
+ }
178
+ this.cbs.forEach((cb) => {
179
+ cb?.(c);
180
+ });
181
+ }
182
+ }
183
+ export {
184
+ ColorPicker as default
185
+ };