inital commit

This commit is contained in:
2026-01-01 15:25:19 +05:30
commit f0ae49465a
36361 changed files with 4894111 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
/**
* [[include:modules/widget/color-picker/README.md]]
* @packageDocumentation
* @module modules/widget/color-picker
*/
import type { IJodit } from "../../../types/index";
/**
* Build color picker
*
* @param callback - Callback 'function (color) \{\}'
* @param coldColor - Color value ex. #fff or rgb(123, 123, 123) or rgba(123, 123, 123, 1)
* @example
* ```javascript
* const tabs = TabsWidget(editor, {
* 'Text': ColorPickerWidget(editor, function (color) {
* box.style.color = color;
* }, box.style.color),
* 'Background': ColorPickerWidget(editor, function (color) {
* box.style.backgroundColor = color;
* }, box.style.backgroundColor),
* });
* ```
*/
export declare const ColorPickerWidget: (editor: IJodit, callback: (newColor: string) => void, coldColor: string) => HTMLDivElement;

View File

@@ -0,0 +1,89 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
import { Dom } from "../../../core/dom/index.js";
import { attr, hasBrowserColorPicker, isArray, isFunction, isPlainObject, normalizeColor, refs } from "../../../core/helpers/index.js";
import { Icon } from "../../../core/ui/index.js";
import paletteIcon from "./palette.svg.js";
Icon.set('palette', paletteIcon);
/**
* Build color picker
*
* @param callback - Callback 'function (color) \{\}'
* @param coldColor - Color value ex. #fff or rgb(123, 123, 123) or rgba(123, 123, 123, 1)
* @example
* ```javascript
* const tabs = TabsWidget(editor, {
* 'Text': ColorPickerWidget(editor, function (color) {
* box.style.color = color;
* }, box.style.color),
* 'Background': ColorPickerWidget(editor, function (color) {
* box.style.backgroundColor = color;
* }, box.style.backgroundColor),
* });
* ```
*/
export const ColorPickerWidget = (editor, callback, coldColor) => {
const cn = 'jodit-color-picker', valueHex = normalizeColor(coldColor), form = editor.c.div(cn), iconPalette = editor.o.textIcons
? `<span>${editor.i18n('palette')}</span>`
: Icon.get('palette'), eachColor = (colors) => {
const stack = [];
if (isPlainObject(colors)) {
Object.keys(colors).forEach(key => {
stack.push(`<div class="${cn}__group ${cn}__group-${key}">`);
stack.push(eachColor(colors[key]));
stack.push('</div>');
});
}
else if (isArray(colors)) {
colors.forEach(color => {
stack.push(`<span class='${cn}__color-item ${valueHex === color
? cn + '__color-item_active_true'
: ''}' title="${color}" style="background-color:${color}" data-color="${color}"></span>`);
});
}
return stack.join('');
};
form.appendChild(editor.c.fromHTML(`<div class="${cn}__groups">${eachColor(editor.o.colors)}</div>`));
form.appendChild(editor.c.fromHTML(`<div data-ref="extra" class="${cn}__extra"></div>`));
const { extra } = refs(form);
if (editor.o.showBrowserColorPicker && hasBrowserColorPicker()) {
extra.appendChild(editor.c.fromHTML(`<div class="${cn}__native">${iconPalette}<input type="color" value="#ffffff"/></div>`));
editor.e.on(form, 'change', (e) => {
e.stopPropagation();
const target = e.target;
if (!target || !target.tagName || !Dom.isTag(target, 'input')) {
return;
}
const color = target.value || '';
if (isFunction(callback)) {
callback(color);
}
e.preventDefault();
});
}
editor.e.on(form, 'mousedown touchend', (e) => {
e.stopPropagation();
e.preventDefault();
let target = e.target;
if ((!target ||
!target.tagName ||
Dom.isTag(target, 'svg') ||
Dom.isTag(target, 'path')) &&
target.parentNode) {
target = Dom.closest(target.parentNode, 'span', editor.editor);
}
if (!Dom.isTag(target, 'span') ||
!target.classList.contains(cn + '__color-item')) {
return;
}
const color = attr(target, '-color') || '';
if (callback && isFunction(callback)) {
callback(color);
}
});
editor.e.fire('afterGenerateColorPicker', form, extra, callback, valueHex);
return form;
};

View File

@@ -0,0 +1 @@
export default "<svg xmlns='http://www.w3.org/2000/svg' x=\"0px\" y=\"0px\" viewBox=\"0 0 459 459\"> <g> <path d=\"M229.5,0C102,0,0,102,0,229.5S102,459,229.5,459c20.4,0,38.25-17.85,38.25-38.25c0-10.2-2.55-17.85-10.2-25.5 c-5.1-7.65-10.2-15.3-10.2-25.5c0-20.4,17.851-38.25,38.25-38.25h45.9c71.4,0,127.5-56.1,127.5-127.5C459,91.8,357,0,229.5,0z M89.25,229.5c-20.4,0-38.25-17.85-38.25-38.25S68.85,153,89.25,153s38.25,17.85,38.25,38.25S109.65,229.5,89.25,229.5z M165.75,127.5c-20.4,0-38.25-17.85-38.25-38.25S145.35,51,165.75,51S204,68.85,204,89.25S186.15,127.5,165.75,127.5z M293.25,127.5c-20.4,0-38.25-17.85-38.25-38.25S272.85,51,293.25,51s38.25,17.85,38.25,38.25S313.65,127.5,293.25,127.5z M369.75,229.5c-20.4,0-38.25-17.85-38.25-38.25S349.35,153,369.75,153S408,170.85,408,191.25S390.15,229.5,369.75,229.5z\" /> </g> </svg> ";

View File

@@ -0,0 +1,37 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
/**
* [[include:modules/widget/file-selector/README.md]]
* @packageDocumentation
* @module modules/widget/file-selector
*/
import type { IFileBrowserCallBackData, IJodit } from "../../../types/index";
interface ImageSelectorCallbacks {
/**
* Function that will be called when the user enters the URL of the tab image and alternative text for images
*/
url?: (this: IJodit, url: string, alt: string) => void;
/**
* Function that will be called when the user clicks on the file browser tab,
* and then choose any image in the window that opens
*/
filebrowser?: (data: IFileBrowserCallBackData) => void;
/**
* Function that will be called when the user selects a file or using drag and drop files to the `Upload` tab
*/
upload?: ((this: IJodit, data: IFileBrowserCallBackData) => void) | true;
}
/**
* Generate 3 tabs
* upload - Use Drag and Drop
* url - By specifying the image url
* filebrowser - After opening the file browser. In the absence of one of the parameters will be less tabs
*
* @param callbacks - Object with keys `url`, `upload` and `filebrowser`, values which are callback
* functions with different parameters
*/
export declare const FileSelectorWidget: (editor: IJodit, callbacks: ImageSelectorCallbacks, elm: HTMLElement | null, close: () => void, isImage?: boolean) => HTMLDivElement;
export {};

View File

@@ -0,0 +1,120 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
import { Dom } from "../../../core/dom/dom.js";
import { $$, attr, isFunction } from "../../../core/helpers/index.js";
import { UIBlock, UIButton, UIForm, UIInput } from "../../../core/ui/index.js";
import { TabsWidget } from "../tabs/tabs.js";
/**
* Generate 3 tabs
* upload - Use Drag and Drop
* url - By specifying the image url
* filebrowser - After opening the file browser. In the absence of one of the parameters will be less tabs
*
* @param callbacks - Object with keys `url`, `upload` and `filebrowser`, values which are callback
* functions with different parameters
*/
export const FileSelectorWidget = (editor, callbacks, elm, close, isImage = true) => {
let currentImage;
const tabs = [];
const options = editor.o.uploader;
if (callbacks.upload &&
(options.url ||
options.insertImageAsBase64URI ||
options.customUploadFunction)) {
const dragBox = editor.c.fromHTML('<div class="jodit-drag-and-drop__file-box">' +
`<strong>${editor.i18n(isImage ? 'Drop image' : 'Drop file')}</strong>` +
`<span><br>${editor.i18n('or click')}</span>` +
`<input type="file" accept="${isImage ? 'image/*' : '*'}" tabindex="-1" dir="auto" multiple=""/>` +
'</div>');
editor.uploader.bind(dragBox, resp => {
const handler = isFunction(callbacks.upload)
? callbacks.upload
: options.defaultHandlerSuccess;
if (isFunction(handler)) {
handler.call(editor, resp);
}
editor.e.fire('closeAllPopups');
}, error => {
editor.message.error(error.message);
editor.e.fire('closeAllPopups');
});
tabs.push({
icon: 'upload',
name: 'Upload',
content: dragBox
});
}
if (callbacks.filebrowser) {
if (editor.o.filebrowser.ajax.url || editor.o.filebrowser.items.url) {
tabs.push({
icon: 'folder',
name: 'Browse',
content: () => {
close && close();
if (callbacks.filebrowser) {
editor.filebrowser.open(callbacks.filebrowser, isImage);
}
}
});
}
}
if (callbacks.url) {
const button = new UIButton(editor, {
type: 'submit',
variant: 'primary',
text: 'Insert'
}), form = new UIForm(editor, [
new UIInput(editor, {
required: true,
label: 'URL',
name: 'url',
type: 'text',
placeholder: 'https://'
}),
new UIInput(editor, {
name: 'text',
label: 'Alternative text'
}),
new UIBlock(editor, [button])
]);
currentImage = null;
if (elm &&
!Dom.isText(elm) &&
!Dom.isComment(elm) &&
(Dom.isTag(elm, 'img') || $$('img', elm).length)) {
currentImage = elm.tagName === 'IMG' ? elm : $$('img', elm)[0];
val(form.container, 'input[name=url]', attr(currentImage, 'src'));
val(form.container, 'input[name=text]', attr(currentImage, 'alt'));
button.state.text = 'Update';
}
if (elm && Dom.isTag(elm, 'a')) {
val(form.container, 'input[name=url]', attr(elm, 'href'));
val(form.container, 'input[name=text]', attr(elm, 'title'));
button.state.text = 'Update';
}
form.onSubmit(data => {
if (isFunction(callbacks.url)) {
callbacks.url.call(editor, data.url, data.text);
}
});
tabs.push({
icon: 'link',
name: 'URL',
content: form.container
});
}
return TabsWidget(editor, tabs);
};
function val(elm, selector, value) {
const child = elm.querySelector(selector);
if (!child) {
return '';
}
if (value) {
child.value = value;
}
return child.value;
}

13
node_modules/jodit/esm/modules/widget/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
/**
* [[include:modules/widget/README.md]]
* @packageDocumentation
* @module modules/widget
*/
export * from "./color-picker/color-picker";
export * from "./file-selector/file-selector";
export * from "./tabs/tabs";

13
node_modules/jodit/esm/modules/widget/index.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
/**
* [[include:modules/widget/README.md]]
* @packageDocumentation
* @module modules/widget
*/
export * from "./color-picker/color-picker.js";
export * from "./file-selector/file-selector.js";
export * from "./tabs/tabs.js";

48
node_modules/jodit/esm/modules/widget/tabs/tabs.d.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
/**
* [[include:modules/widget/tabs/README.md]]
* @packageDocumentation
* @module modules/widget/tabs
*/
import type { IViewBased } from "../../../types/index";
import { UIElement } from "../../../core/ui/index";
export interface TabOption {
icon?: string;
name: string;
content: HTMLElement | ((this: IViewBased) => void) | UIElement;
}
/**
* Build tabs system
*
* @param tabs - PlainObject where 'key' will be tab's Title and `value` is tab's content
* @param state - You can use for this param any HTML element for remembering active tab
*
* @example
* ```javascript
* const editor = Jodit.make('#editor');
* const tabs = Jodit.modules.TabsWidget(editor, [
* { name: 'Images', content: '<div>Images</div>' },
* {
* name: 'Title 2',
* content: editor.c.fromHTML('<div>Some content</div>')
* },
* {
* name: 'Color Picker',
* content: ColorPickerWidget(
* editor,
* function (color) {
* box.style.color = color;
* },
* box.style.color
* )
* }
* ]);
* ```
*/
export declare const TabsWidget: (jodit: IViewBased, tabs: TabOption[], state?: {
activeTab: string;
}) => HTMLDivElement;

124
node_modules/jodit/esm/modules/widget/tabs/tabs.js generated vendored Normal file
View File

@@ -0,0 +1,124 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
import { Component } from "../../../core/component/index.js";
import { Dom } from "../../../core/dom/dom.js";
import { isFunction } from "../../../core/helpers/checker/is-function.js";
import { attr } from "../../../core/helpers/utils/attr.js";
import { Button, UIElement } from "../../../core/ui/index.js";
/**
* Build tabs system
*
* @param tabs - PlainObject where 'key' will be tab's Title and `value` is tab's content
* @param state - You can use for this param any HTML element for remembering active tab
*
* @example
* ```javascript
* const editor = Jodit.make('#editor');
* const tabs = Jodit.modules.TabsWidget(editor, [
* { name: 'Images', content: '<div>Images</div>' },
* {
* name: 'Title 2',
* content: editor.c.fromHTML('<div>Some content</div>')
* },
* {
* name: 'Color Picker',
* content: ColorPickerWidget(
* editor,
* function (color) {
* box.style.color = color;
* },
* box.style.color
* )
* }
* ]);
* ```
*/
export const TabsWidget = (jodit, tabs, state) => {
const box = jodit.c.div('jodit-tabs');
const tabBox = jodit.c.div('jodit-tabs__wrapper');
const buttons = jodit.c.div('jodit-tabs__buttons');
attr(buttons, {
role: 'tablist',
'aria-orientation': 'horizontal'
});
const nameToTab = {};
const buttonList = [];
let firstTab = '';
box.appendChild(buttons);
box.appendChild(tabBox);
const setActive = (tab) => {
if (!nameToTab[tab]) {
return;
}
buttonList.forEach(b => {
b.state.activated = false;
});
Object.values(nameToTab).forEach(({ tab }) => tab.classList.remove('jodit-tab_active'));
nameToTab[tab].button.state.activated = true;
nameToTab[tab].tab.classList.add('jodit-tab_active');
};
tabs.forEach(({ icon, name, content }) => {
const tab = jodit.c.div('jodit-tab');
attr(tab, {
role: 'tabpanel'
});
const button = Button(jodit, icon || name, name);
button.state.role = 'tab';
// Stop lose the focus
jodit.e.on(button.container, 'pointerdown', (e) => e.preventDefault());
if (!firstTab) {
firstTab = name;
}
buttons.appendChild(button.container);
buttonList.push(button);
button.container.classList.add('jodit-tabs__button', 'jodit-tabs__button_columns_' + tabs.length);
if (!isFunction(content)) {
tab.appendChild(Component.isInstanceOf(content, UIElement)
? content.container
: content);
}
else {
tab.appendChild(jodit.c.div('jodit-tab_empty'));
}
tabBox.appendChild(tab);
button.onAction(() => {
setActive(name);
if (isFunction(content) && !Dom.isElement(content)) {
content.call(jodit);
}
if (state) {
state.activeTab = name;
}
return false;
});
nameToTab[name] = {
button,
tab
};
});
Object.values(nameToTab).forEach(({ button }) => {
button.container.style.width = (100 / tabs.length).toFixed(10) + '%';
});
const tab = !state || !state.activeTab || !nameToTab[state.activeTab]
? firstTab
: state.activeTab;
setActive(tab);
if (state) {
let activeTab = state.activeTab;
Object.defineProperty(state, 'activeTab', {
configurable: true,
enumerable: false,
get() {
return activeTab;
},
set(value) {
activeTab = value;
setActive(value);
}
});
}
return box;
};