@kedataindo/docflow-plugins 0.0.31 → 0.0.32
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/index.cjs +448 -5
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +440 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -39,9 +39,14 @@ __export(index_exports, {
|
|
|
39
39
|
CiteEngine: () => CiteEngine,
|
|
40
40
|
CommentMarkExtension: () => CommentMark,
|
|
41
41
|
DEFAULT_CSL_STYLE: () => DEFAULT_CSL_STYLE,
|
|
42
|
+
DateChipNode: () => DateChipNode,
|
|
43
|
+
DropdownChipNode: () => DropdownChipNode,
|
|
44
|
+
FileChipNode: () => FileChipNode,
|
|
42
45
|
FontSizeExtension: () => import_docflow_core14.FontSizeExtension,
|
|
43
46
|
FootnoteNode: () => FootnoteNode,
|
|
47
|
+
LocationChipNode: () => LocationChipNode,
|
|
44
48
|
PageBreak: () => PageBreak,
|
|
49
|
+
PeopleChipNode: () => PeopleChipNode,
|
|
45
50
|
SlashMenuExtension: () => SlashMenuExtension,
|
|
46
51
|
TocEntryNode: () => TocEntryNode,
|
|
47
52
|
TocNode: () => TocNode,
|
|
@@ -76,6 +81,7 @@ __export(index_exports, {
|
|
|
76
81
|
sanitizeCiteprocHtml: () => sanitizeCiteprocHtml,
|
|
77
82
|
slashMenuPlugin: () => slashMenuPlugin,
|
|
78
83
|
slashState: () => slashState,
|
|
84
|
+
smartElementsPlugin: () => smartElementsPlugin,
|
|
79
85
|
tablePlugin: () => tablePlugin,
|
|
80
86
|
textColorPlugin: () => textColorPlugin,
|
|
81
87
|
tocPlugin: () => tocPlugin
|
|
@@ -2723,10 +2729,440 @@ var commentPlugin = {
|
|
|
2723
2729
|
commands: {}
|
|
2724
2730
|
};
|
|
2725
2731
|
|
|
2726
|
-
// src/
|
|
2732
|
+
// src/smartElements.ts
|
|
2727
2733
|
var import_core10 = require("@tiptap/core");
|
|
2728
|
-
var import_state2 = require("@tiptap/pm/state");
|
|
2729
2734
|
var import_docflow_core19 = require("@kedataindo/docflow-core");
|
|
2735
|
+
function todayISO() {
|
|
2736
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2737
|
+
}
|
|
2738
|
+
function formatDate(iso) {
|
|
2739
|
+
if (!iso) return "Pick a date";
|
|
2740
|
+
const d = /* @__PURE__ */ new Date(iso + "T00:00:00");
|
|
2741
|
+
if (isNaN(d.getTime())) return "Pick a date";
|
|
2742
|
+
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
|
|
2743
|
+
}
|
|
2744
|
+
function initialOf(name) {
|
|
2745
|
+
return (name || "?").trim().charAt(0).toUpperCase() || "?";
|
|
2746
|
+
}
|
|
2747
|
+
var DEFAULT_STATUSES = ["To Do", "In Progress", "Review", "Approved"];
|
|
2748
|
+
function slugify(s) {
|
|
2749
|
+
return s.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
2750
|
+
}
|
|
2751
|
+
var DateChipNode = import_core10.Node.create({
|
|
2752
|
+
name: "dateChip",
|
|
2753
|
+
group: "inline",
|
|
2754
|
+
inline: true,
|
|
2755
|
+
selectable: true,
|
|
2756
|
+
draggable: false,
|
|
2757
|
+
atom: true,
|
|
2758
|
+
addAttributes() {
|
|
2759
|
+
return {
|
|
2760
|
+
date: {
|
|
2761
|
+
default: todayISO(),
|
|
2762
|
+
parseHTML: (el) => el.getAttribute("data-date") ?? todayISO(),
|
|
2763
|
+
renderHTML: (attrs) => ({ "data-date": attrs.date ?? "" })
|
|
2764
|
+
}
|
|
2765
|
+
};
|
|
2766
|
+
},
|
|
2767
|
+
parseHTML() {
|
|
2768
|
+
return [{ tag: 'span[data-node-type="date-chip"]' }];
|
|
2769
|
+
},
|
|
2770
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
2771
|
+
return ["span", (0, import_core10.mergeAttributes)(HTMLAttributes, {
|
|
2772
|
+
"data-node-type": "date-chip",
|
|
2773
|
+
class: "docs-chip docs-chip--date"
|
|
2774
|
+
}), formatDate(node.attrs.date)];
|
|
2775
|
+
},
|
|
2776
|
+
addNodeView() {
|
|
2777
|
+
return (props) => {
|
|
2778
|
+
let currentNode = props.node;
|
|
2779
|
+
const getPos = props.getPos;
|
|
2780
|
+
const view = props.view;
|
|
2781
|
+
const dom = document.createElement("span");
|
|
2782
|
+
dom.className = "docs-chip docs-chip--date";
|
|
2783
|
+
dom.setAttribute("data-node-type", "date-chip");
|
|
2784
|
+
dom.setAttribute("contenteditable", "false");
|
|
2785
|
+
const render = () => {
|
|
2786
|
+
if (dom.querySelector("input")) return;
|
|
2787
|
+
dom.textContent = formatDate(currentNode.attrs.date);
|
|
2788
|
+
dom.setAttribute("data-date", currentNode.attrs.date);
|
|
2789
|
+
};
|
|
2790
|
+
render();
|
|
2791
|
+
dom.addEventListener("click", (e) => {
|
|
2792
|
+
e.preventDefault();
|
|
2793
|
+
e.stopPropagation();
|
|
2794
|
+
if (dom.querySelector("input")) return;
|
|
2795
|
+
const input = document.createElement("input");
|
|
2796
|
+
input.type = "date";
|
|
2797
|
+
input.value = currentNode.attrs.date;
|
|
2798
|
+
input.className = "docs-chip-date-input";
|
|
2799
|
+
dom.replaceChildren(input);
|
|
2800
|
+
input.focus();
|
|
2801
|
+
const commit = () => {
|
|
2802
|
+
const newVal = input.value;
|
|
2803
|
+
const pos = getPos();
|
|
2804
|
+
if (typeof pos === "number") {
|
|
2805
|
+
view.dispatch(view.state.tr.setNodeMarkup(pos, void 0, { date: newVal }));
|
|
2806
|
+
}
|
|
2807
|
+
setTimeout(render, 30);
|
|
2808
|
+
};
|
|
2809
|
+
input.addEventListener("change", commit);
|
|
2810
|
+
input.addEventListener("blur", () => setTimeout(render, 30));
|
|
2811
|
+
});
|
|
2812
|
+
return {
|
|
2813
|
+
dom,
|
|
2814
|
+
update(updatedNode) {
|
|
2815
|
+
if (updatedNode.type.name !== "dateChip") return false;
|
|
2816
|
+
currentNode = updatedNode;
|
|
2817
|
+
render();
|
|
2818
|
+
return true;
|
|
2819
|
+
}
|
|
2820
|
+
};
|
|
2821
|
+
};
|
|
2822
|
+
}
|
|
2823
|
+
});
|
|
2824
|
+
var PeopleChipNode = import_core10.Node.create({
|
|
2825
|
+
name: "peopleChip",
|
|
2826
|
+
group: "inline",
|
|
2827
|
+
inline: true,
|
|
2828
|
+
selectable: true,
|
|
2829
|
+
draggable: false,
|
|
2830
|
+
atom: true,
|
|
2831
|
+
addAttributes() {
|
|
2832
|
+
return {
|
|
2833
|
+
userId: {
|
|
2834
|
+
default: "",
|
|
2835
|
+
parseHTML: (el) => el.getAttribute("data-user-id") ?? "",
|
|
2836
|
+
renderHTML: (attrs) => attrs.userId ? { "data-user-id": attrs.userId } : {}
|
|
2837
|
+
},
|
|
2838
|
+
name: {
|
|
2839
|
+
default: "",
|
|
2840
|
+
parseHTML: (el) => el.getAttribute("data-name") ?? "",
|
|
2841
|
+
renderHTML: (attrs) => ({ "data-name": attrs.name ?? "" })
|
|
2842
|
+
}
|
|
2843
|
+
};
|
|
2844
|
+
},
|
|
2845
|
+
parseHTML() {
|
|
2846
|
+
return [{ tag: 'span[data-node-type="people-chip"]' }];
|
|
2847
|
+
},
|
|
2848
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
2849
|
+
return ["span", (0, import_core10.mergeAttributes)(HTMLAttributes, {
|
|
2850
|
+
"data-node-type": "people-chip",
|
|
2851
|
+
class: "docs-chip docs-chip--people"
|
|
2852
|
+
}), `@${node.attrs.name || "user"}`];
|
|
2853
|
+
},
|
|
2854
|
+
addNodeView() {
|
|
2855
|
+
return (props) => {
|
|
2856
|
+
let currentNode = props.node;
|
|
2857
|
+
const dom = document.createElement("span");
|
|
2858
|
+
dom.className = "docs-chip docs-chip--people";
|
|
2859
|
+
dom.setAttribute("data-node-type", "people-chip");
|
|
2860
|
+
dom.setAttribute("contenteditable", "false");
|
|
2861
|
+
const render = () => {
|
|
2862
|
+
const name = currentNode.attrs.name || "user";
|
|
2863
|
+
dom.innerHTML = "";
|
|
2864
|
+
const avatar = document.createElement("span");
|
|
2865
|
+
avatar.className = "docs-chip-avatar";
|
|
2866
|
+
avatar.textContent = initialOf(name);
|
|
2867
|
+
dom.appendChild(avatar);
|
|
2868
|
+
const label = document.createElement("span");
|
|
2869
|
+
label.className = "docs-chip-label";
|
|
2870
|
+
label.textContent = "@" + name;
|
|
2871
|
+
dom.appendChild(label);
|
|
2872
|
+
};
|
|
2873
|
+
render();
|
|
2874
|
+
return {
|
|
2875
|
+
dom,
|
|
2876
|
+
update(updatedNode) {
|
|
2877
|
+
if (updatedNode.type.name !== "peopleChip") return false;
|
|
2878
|
+
currentNode = updatedNode;
|
|
2879
|
+
render();
|
|
2880
|
+
return true;
|
|
2881
|
+
}
|
|
2882
|
+
};
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2885
|
+
});
|
|
2886
|
+
var FileChipNode = import_core10.Node.create({
|
|
2887
|
+
name: "fileChip",
|
|
2888
|
+
group: "inline",
|
|
2889
|
+
inline: true,
|
|
2890
|
+
selectable: true,
|
|
2891
|
+
draggable: false,
|
|
2892
|
+
atom: true,
|
|
2893
|
+
addAttributes() {
|
|
2894
|
+
return {
|
|
2895
|
+
fileId: {
|
|
2896
|
+
default: "",
|
|
2897
|
+
parseHTML: (el) => el.getAttribute("data-file-id") ?? "",
|
|
2898
|
+
renderHTML: (attrs) => attrs.fileId ? { "data-file-id": attrs.fileId } : {}
|
|
2899
|
+
},
|
|
2900
|
+
name: {
|
|
2901
|
+
default: "",
|
|
2902
|
+
parseHTML: (el) => el.getAttribute("data-name") ?? "",
|
|
2903
|
+
renderHTML: (attrs) => ({ "data-name": attrs.name ?? "" })
|
|
2904
|
+
}
|
|
2905
|
+
};
|
|
2906
|
+
},
|
|
2907
|
+
parseHTML() {
|
|
2908
|
+
return [{ tag: 'span[data-node-type="file-chip"]' }];
|
|
2909
|
+
},
|
|
2910
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
2911
|
+
return ["span", (0, import_core10.mergeAttributes)(HTMLAttributes, {
|
|
2912
|
+
"data-node-type": "file-chip",
|
|
2913
|
+
class: "docs-chip docs-chip--file"
|
|
2914
|
+
}), node.attrs.name || "file"];
|
|
2915
|
+
},
|
|
2916
|
+
addNodeView() {
|
|
2917
|
+
return (props) => {
|
|
2918
|
+
let currentNode = props.node;
|
|
2919
|
+
const dom = document.createElement("span");
|
|
2920
|
+
dom.className = "docs-chip docs-chip--file";
|
|
2921
|
+
dom.setAttribute("data-node-type", "file-chip");
|
|
2922
|
+
dom.setAttribute("contenteditable", "false");
|
|
2923
|
+
const render = () => {
|
|
2924
|
+
const name = currentNode.attrs.name || "Untitled file";
|
|
2925
|
+
dom.innerHTML = "";
|
|
2926
|
+
const icon = document.createElement("span");
|
|
2927
|
+
icon.className = "docs-chip-icon";
|
|
2928
|
+
icon.textContent = "\u{1F5CE}";
|
|
2929
|
+
dom.appendChild(icon);
|
|
2930
|
+
const label = document.createElement("span");
|
|
2931
|
+
label.className = "docs-chip-label";
|
|
2932
|
+
label.textContent = name;
|
|
2933
|
+
dom.appendChild(label);
|
|
2934
|
+
};
|
|
2935
|
+
render();
|
|
2936
|
+
return {
|
|
2937
|
+
dom,
|
|
2938
|
+
update(updatedNode) {
|
|
2939
|
+
if (updatedNode.type.name !== "fileChip") return false;
|
|
2940
|
+
currentNode = updatedNode;
|
|
2941
|
+
render();
|
|
2942
|
+
return true;
|
|
2943
|
+
}
|
|
2944
|
+
};
|
|
2945
|
+
};
|
|
2946
|
+
}
|
|
2947
|
+
});
|
|
2948
|
+
var DropdownChipNode = import_core10.Node.create({
|
|
2949
|
+
name: "dropdownChip",
|
|
2950
|
+
group: "inline",
|
|
2951
|
+
inline: true,
|
|
2952
|
+
selectable: true,
|
|
2953
|
+
draggable: false,
|
|
2954
|
+
atom: true,
|
|
2955
|
+
addAttributes() {
|
|
2956
|
+
return {
|
|
2957
|
+
options: {
|
|
2958
|
+
default: DEFAULT_STATUSES,
|
|
2959
|
+
parseHTML: (el) => {
|
|
2960
|
+
const raw = el.getAttribute("data-options") ?? "";
|
|
2961
|
+
const list = raw ? raw.split("|") : [];
|
|
2962
|
+
return list.length ? list : DEFAULT_STATUSES;
|
|
2963
|
+
},
|
|
2964
|
+
renderHTML: (attrs) => ({
|
|
2965
|
+
"data-options": (attrs.options ?? []).join("|")
|
|
2966
|
+
})
|
|
2967
|
+
},
|
|
2968
|
+
selected: {
|
|
2969
|
+
default: DEFAULT_STATUSES[0],
|
|
2970
|
+
parseHTML: (el) => el.getAttribute("data-selected") ?? DEFAULT_STATUSES[0],
|
|
2971
|
+
renderHTML: (attrs) => ({ "data-selected": attrs.selected ?? "" })
|
|
2972
|
+
}
|
|
2973
|
+
};
|
|
2974
|
+
},
|
|
2975
|
+
parseHTML() {
|
|
2976
|
+
return [{ tag: 'span[data-node-type="dropdown-chip"]' }];
|
|
2977
|
+
},
|
|
2978
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
2979
|
+
return ["span", (0, import_core10.mergeAttributes)(HTMLAttributes, {
|
|
2980
|
+
"data-node-type": "dropdown-chip",
|
|
2981
|
+
class: "docs-chip docs-chip--dropdown"
|
|
2982
|
+
}), node.attrs.selected || ""];
|
|
2983
|
+
},
|
|
2984
|
+
addNodeView() {
|
|
2985
|
+
return (props) => {
|
|
2986
|
+
let currentNode = props.node;
|
|
2987
|
+
const getPos = props.getPos;
|
|
2988
|
+
const view = props.view;
|
|
2989
|
+
const dom = document.createElement("span");
|
|
2990
|
+
dom.className = "docs-chip docs-chip--dropdown";
|
|
2991
|
+
dom.setAttribute("data-node-type", "dropdown-chip");
|
|
2992
|
+
dom.setAttribute("contenteditable", "false");
|
|
2993
|
+
const render = () => {
|
|
2994
|
+
const opts = currentNode.attrs.options ?? DEFAULT_STATUSES;
|
|
2995
|
+
const sel = currentNode.attrs.selected ?? (opts[0] ?? "");
|
|
2996
|
+
dom.innerHTML = "";
|
|
2997
|
+
const select = document.createElement("select");
|
|
2998
|
+
select.className = "docs-chip-select";
|
|
2999
|
+
select.addEventListener("mousedown", (e) => e.stopPropagation());
|
|
3000
|
+
for (const opt of opts) {
|
|
3001
|
+
const o = document.createElement("option");
|
|
3002
|
+
o.value = opt;
|
|
3003
|
+
o.textContent = opt;
|
|
3004
|
+
if (opt === sel) o.selected = true;
|
|
3005
|
+
select.appendChild(o);
|
|
3006
|
+
}
|
|
3007
|
+
select.addEventListener("change", () => {
|
|
3008
|
+
const pos = getPos();
|
|
3009
|
+
if (typeof pos === "number") {
|
|
3010
|
+
view.dispatch(view.state.tr.setNodeMarkup(pos, void 0, {
|
|
3011
|
+
...currentNode.attrs,
|
|
3012
|
+
selected: select.value
|
|
3013
|
+
}));
|
|
3014
|
+
}
|
|
3015
|
+
});
|
|
3016
|
+
dom.appendChild(select);
|
|
3017
|
+
};
|
|
3018
|
+
render();
|
|
3019
|
+
return {
|
|
3020
|
+
dom,
|
|
3021
|
+
update(updatedNode) {
|
|
3022
|
+
if (updatedNode.type.name !== "dropdownChip") return false;
|
|
3023
|
+
currentNode = updatedNode;
|
|
3024
|
+
render();
|
|
3025
|
+
return true;
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
});
|
|
3031
|
+
var LocationChipNode = import_core10.Node.create({
|
|
3032
|
+
name: "locationChip",
|
|
3033
|
+
group: "inline",
|
|
3034
|
+
inline: true,
|
|
3035
|
+
selectable: true,
|
|
3036
|
+
draggable: false,
|
|
3037
|
+
atom: true,
|
|
3038
|
+
addAttributes() {
|
|
3039
|
+
return {
|
|
3040
|
+
label: {
|
|
3041
|
+
default: "",
|
|
3042
|
+
parseHTML: (el) => el.getAttribute("data-label") ?? "",
|
|
3043
|
+
renderHTML: (attrs) => ({ "data-label": attrs.label ?? "" })
|
|
3044
|
+
},
|
|
3045
|
+
lat: {
|
|
3046
|
+
default: null,
|
|
3047
|
+
parseHTML: (el) => {
|
|
3048
|
+
const v = el.getAttribute("data-lat");
|
|
3049
|
+
return v === null ? null : Number(v);
|
|
3050
|
+
},
|
|
3051
|
+
renderHTML: (attrs) => attrs.lat != null ? { "data-lat": attrs.lat } : {}
|
|
3052
|
+
},
|
|
3053
|
+
lng: {
|
|
3054
|
+
default: null,
|
|
3055
|
+
parseHTML: (el) => {
|
|
3056
|
+
const v = el.getAttribute("data-lng");
|
|
3057
|
+
return v === null ? null : Number(v);
|
|
3058
|
+
},
|
|
3059
|
+
renderHTML: (attrs) => attrs.lng != null ? { "data-lng": attrs.lng } : {}
|
|
3060
|
+
}
|
|
3061
|
+
};
|
|
3062
|
+
},
|
|
3063
|
+
parseHTML() {
|
|
3064
|
+
return [{ tag: 'span[data-node-type="location-chip"]' }];
|
|
3065
|
+
},
|
|
3066
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
3067
|
+
return ["span", (0, import_core10.mergeAttributes)(HTMLAttributes, {
|
|
3068
|
+
"data-node-type": "location-chip",
|
|
3069
|
+
class: "docs-chip docs-chip--location"
|
|
3070
|
+
}), node.attrs.label || ""];
|
|
3071
|
+
},
|
|
3072
|
+
addNodeView() {
|
|
3073
|
+
return (props) => {
|
|
3074
|
+
let currentNode = props.node;
|
|
3075
|
+
const dom = document.createElement("span");
|
|
3076
|
+
dom.className = "docs-chip docs-chip--location";
|
|
3077
|
+
dom.setAttribute("data-node-type", "location-chip");
|
|
3078
|
+
dom.setAttribute("contenteditable", "false");
|
|
3079
|
+
const render = () => {
|
|
3080
|
+
const label = currentNode.attrs.label || "Add location";
|
|
3081
|
+
dom.innerHTML = "";
|
|
3082
|
+
const icon = document.createElement("span");
|
|
3083
|
+
icon.className = "docs-chip-icon";
|
|
3084
|
+
icon.textContent = "\u{1F4CD}";
|
|
3085
|
+
dom.appendChild(icon);
|
|
3086
|
+
const lbl = document.createElement("span");
|
|
3087
|
+
lbl.className = "docs-chip-label";
|
|
3088
|
+
lbl.textContent = label;
|
|
3089
|
+
dom.appendChild(lbl);
|
|
3090
|
+
};
|
|
3091
|
+
render();
|
|
3092
|
+
return {
|
|
3093
|
+
dom,
|
|
3094
|
+
update(updatedNode) {
|
|
3095
|
+
if (updatedNode.type.name !== "locationChip") return false;
|
|
3096
|
+
currentNode = updatedNode;
|
|
3097
|
+
render();
|
|
3098
|
+
return true;
|
|
3099
|
+
}
|
|
3100
|
+
};
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
3103
|
+
});
|
|
3104
|
+
var smartElementsPlugin = (0, import_docflow_core19.definePlugin)({
|
|
3105
|
+
id: "smart-elements",
|
|
3106
|
+
tiptapExtensions: [
|
|
3107
|
+
DateChipNode,
|
|
3108
|
+
PeopleChipNode,
|
|
3109
|
+
FileChipNode,
|
|
3110
|
+
DropdownChipNode,
|
|
3111
|
+
LocationChipNode
|
|
3112
|
+
],
|
|
3113
|
+
slashCommands: [
|
|
3114
|
+
{ name: "Date", command: "insertDateChip" },
|
|
3115
|
+
{ name: "People", command: "insertPeopleChip" },
|
|
3116
|
+
{ name: "File", command: "insertFileChip" },
|
|
3117
|
+
{ name: "Dropdown", command: "insertDropdownChip" },
|
|
3118
|
+
{ name: "Location", command: "insertLocationChip" }
|
|
3119
|
+
],
|
|
3120
|
+
commands: {
|
|
3121
|
+
insertDateChip: (editor) => {
|
|
3122
|
+
return editor.chain().focus().insertContent({
|
|
3123
|
+
type: "dateChip",
|
|
3124
|
+
attrs: { date: todayISO() }
|
|
3125
|
+
}).run();
|
|
3126
|
+
},
|
|
3127
|
+
insertPeopleChip: (editor) => {
|
|
3128
|
+
const name = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter user name:", "") ?? "" : "";
|
|
3129
|
+
if (!name.trim()) return false;
|
|
3130
|
+
const trimmed = name.trim();
|
|
3131
|
+
return editor.chain().focus().insertContent({
|
|
3132
|
+
type: "peopleChip",
|
|
3133
|
+
attrs: { userId: slugify(trimmed), name: trimmed }
|
|
3134
|
+
}).run();
|
|
3135
|
+
},
|
|
3136
|
+
insertFileChip: (editor) => {
|
|
3137
|
+
const name = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter file/document name:", "") ?? "" : "";
|
|
3138
|
+
if (!name.trim()) return false;
|
|
3139
|
+
const trimmed = name.trim();
|
|
3140
|
+
return editor.chain().focus().insertContent({
|
|
3141
|
+
type: "fileChip",
|
|
3142
|
+
attrs: { fileId: slugify(trimmed), name: trimmed }
|
|
3143
|
+
}).run();
|
|
3144
|
+
},
|
|
3145
|
+
insertDropdownChip: (editor) => {
|
|
3146
|
+
return editor.chain().focus().insertContent({
|
|
3147
|
+
type: "dropdownChip",
|
|
3148
|
+
attrs: { options: DEFAULT_STATUSES, selected: DEFAULT_STATUSES[0] }
|
|
3149
|
+
}).run();
|
|
3150
|
+
},
|
|
3151
|
+
insertLocationChip: (editor) => {
|
|
3152
|
+
const label = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter location name:", "") ?? "" : "";
|
|
3153
|
+
if (!label.trim()) return false;
|
|
3154
|
+
return editor.chain().focus().insertContent({
|
|
3155
|
+
type: "locationChip",
|
|
3156
|
+
attrs: { label: label.trim() }
|
|
3157
|
+
}).run();
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
3161
|
+
|
|
3162
|
+
// src/slashMenu.ts
|
|
3163
|
+
var import_core11 = require("@tiptap/core");
|
|
3164
|
+
var import_state2 = require("@tiptap/pm/state");
|
|
3165
|
+
var import_docflow_core20 = require("@kedataindo/docflow-core");
|
|
2730
3166
|
var slashState = {
|
|
2731
3167
|
open: false,
|
|
2732
3168
|
query: "",
|
|
@@ -2780,7 +3216,7 @@ function getRegisteredCommands() {
|
|
|
2780
3216
|
return true;
|
|
2781
3217
|
});
|
|
2782
3218
|
}
|
|
2783
|
-
var SlashMenuExtension =
|
|
3219
|
+
var SlashMenuExtension = import_core11.Extension.create({
|
|
2784
3220
|
name: "slashMenu",
|
|
2785
3221
|
addProseMirrorPlugins() {
|
|
2786
3222
|
return [
|
|
@@ -2871,7 +3307,7 @@ var SlashMenuExtension = import_core10.Extension.create({
|
|
|
2871
3307
|
];
|
|
2872
3308
|
}
|
|
2873
3309
|
});
|
|
2874
|
-
var slashMenuPlugin = (0,
|
|
3310
|
+
var slashMenuPlugin = (0, import_docflow_core20.definePlugin)({
|
|
2875
3311
|
id: "slash-menu",
|
|
2876
3312
|
tiptapExtensions: [SlashMenuExtension],
|
|
2877
3313
|
hooks: {
|
|
@@ -2902,7 +3338,8 @@ var defaultPlugins = [
|
|
|
2902
3338
|
highlightPlugin,
|
|
2903
3339
|
citationPlugin,
|
|
2904
3340
|
aiPlugin,
|
|
2905
|
-
commentPlugin
|
|
3341
|
+
commentPlugin,
|
|
3342
|
+
smartElementsPlugin
|
|
2906
3343
|
];
|
|
2907
3344
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2908
3345
|
0 && (module.exports = {
|
|
@@ -2915,9 +3352,14 @@ var defaultPlugins = [
|
|
|
2915
3352
|
CiteEngine,
|
|
2916
3353
|
CommentMarkExtension,
|
|
2917
3354
|
DEFAULT_CSL_STYLE,
|
|
3355
|
+
DateChipNode,
|
|
3356
|
+
DropdownChipNode,
|
|
3357
|
+
FileChipNode,
|
|
2918
3358
|
FontSizeExtension,
|
|
2919
3359
|
FootnoteNode,
|
|
3360
|
+
LocationChipNode,
|
|
2920
3361
|
PageBreak,
|
|
3362
|
+
PeopleChipNode,
|
|
2921
3363
|
SlashMenuExtension,
|
|
2922
3364
|
TocEntryNode,
|
|
2923
3365
|
TocNode,
|
|
@@ -2952,6 +3394,7 @@ var defaultPlugins = [
|
|
|
2952
3394
|
sanitizeCiteprocHtml,
|
|
2953
3395
|
slashMenuPlugin,
|
|
2954
3396
|
slashState,
|
|
3397
|
+
smartElementsPlugin,
|
|
2955
3398
|
tablePlugin,
|
|
2956
3399
|
textColorPlugin,
|
|
2957
3400
|
tocPlugin
|
package/dist/index.d.cts
CHANGED
|
@@ -225,6 +225,13 @@ declare const CommentMark: Mark<any, any>;
|
|
|
225
225
|
*/
|
|
226
226
|
declare const commentPlugin: DocsEditorPlugin;
|
|
227
227
|
|
|
228
|
+
declare const DateChipNode: Node<any, any>;
|
|
229
|
+
declare const PeopleChipNode: Node<any, any>;
|
|
230
|
+
declare const FileChipNode: Node<any, any>;
|
|
231
|
+
declare const DropdownChipNode: Node<any, any>;
|
|
232
|
+
declare const LocationChipNode: Node<any, any>;
|
|
233
|
+
declare const smartElementsPlugin: _kedata_indonesia_docflow_core.DocsEditorPlugin;
|
|
234
|
+
|
|
228
235
|
/**
|
|
229
236
|
* Bibliography — a fully derived block. It stores NOTHING (no attrs): the
|
|
230
237
|
* node view renders the engine's citeproc-sorted entries and repaints on
|
|
@@ -257,4 +264,4 @@ declare const slashMenuPlugin: _kedata_indonesia_docflow_core.DocsEditorPlugin;
|
|
|
257
264
|
|
|
258
265
|
declare const defaultPlugins: _kedata_indonesia_docflow_core.DocsEditorPlugin[];
|
|
259
266
|
|
|
260
|
-
export { AIExtension, type AIPreviewState, BibliographyNode, CitationEngineExtension, CitationNode, CiteEngine, type CommentMarkAttrs, CommentMark as CommentMarkExtension, FootnoteNode, PageBreak, type PlaceholderPluginOptions, SlashMenuExtension, TocEntryNode, TocNode, TocPageNumNode, aiPlugin, aiPluginKey, alignmentPlugin, blockquotePlugin, citationPlugin, codeBlockPlugin, collectHeadings, commentPlugin, createPlaceholderPlugin, defaultPlugins, fontSizePlugin, footnotePlugin, formattingPlugin, getAIPreview, getCitationEngine, headingsPlugin, highlightPlugin, imagePlugin, linkPlugin, listsPlugin, onSlashStateChange, pageBreakPlugin, placeholderPlugin, regenerateToc, registerSlashCommands, slashMenuPlugin, slashState, tablePlugin, textColorPlugin, tocPlugin };
|
|
267
|
+
export { AIExtension, type AIPreviewState, BibliographyNode, CitationEngineExtension, CitationNode, CiteEngine, type CommentMarkAttrs, CommentMark as CommentMarkExtension, DateChipNode, DropdownChipNode, FileChipNode, FootnoteNode, LocationChipNode, PageBreak, PeopleChipNode, type PlaceholderPluginOptions, SlashMenuExtension, TocEntryNode, TocNode, TocPageNumNode, aiPlugin, aiPluginKey, alignmentPlugin, blockquotePlugin, citationPlugin, codeBlockPlugin, collectHeadings, commentPlugin, createPlaceholderPlugin, defaultPlugins, fontSizePlugin, footnotePlugin, formattingPlugin, getAIPreview, getCitationEngine, headingsPlugin, highlightPlugin, imagePlugin, linkPlugin, listsPlugin, onSlashStateChange, pageBreakPlugin, placeholderPlugin, regenerateToc, registerSlashCommands, slashMenuPlugin, slashState, smartElementsPlugin, tablePlugin, textColorPlugin, tocPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -225,6 +225,13 @@ declare const CommentMark: Mark<any, any>;
|
|
|
225
225
|
*/
|
|
226
226
|
declare const commentPlugin: DocsEditorPlugin;
|
|
227
227
|
|
|
228
|
+
declare const DateChipNode: Node<any, any>;
|
|
229
|
+
declare const PeopleChipNode: Node<any, any>;
|
|
230
|
+
declare const FileChipNode: Node<any, any>;
|
|
231
|
+
declare const DropdownChipNode: Node<any, any>;
|
|
232
|
+
declare const LocationChipNode: Node<any, any>;
|
|
233
|
+
declare const smartElementsPlugin: _kedata_indonesia_docflow_core.DocsEditorPlugin;
|
|
234
|
+
|
|
228
235
|
/**
|
|
229
236
|
* Bibliography — a fully derived block. It stores NOTHING (no attrs): the
|
|
230
237
|
* node view renders the engine's citeproc-sorted entries and repaints on
|
|
@@ -257,4 +264,4 @@ declare const slashMenuPlugin: _kedata_indonesia_docflow_core.DocsEditorPlugin;
|
|
|
257
264
|
|
|
258
265
|
declare const defaultPlugins: _kedata_indonesia_docflow_core.DocsEditorPlugin[];
|
|
259
266
|
|
|
260
|
-
export { AIExtension, type AIPreviewState, BibliographyNode, CitationEngineExtension, CitationNode, CiteEngine, type CommentMarkAttrs, CommentMark as CommentMarkExtension, FootnoteNode, PageBreak, type PlaceholderPluginOptions, SlashMenuExtension, TocEntryNode, TocNode, TocPageNumNode, aiPlugin, aiPluginKey, alignmentPlugin, blockquotePlugin, citationPlugin, codeBlockPlugin, collectHeadings, commentPlugin, createPlaceholderPlugin, defaultPlugins, fontSizePlugin, footnotePlugin, formattingPlugin, getAIPreview, getCitationEngine, headingsPlugin, highlightPlugin, imagePlugin, linkPlugin, listsPlugin, onSlashStateChange, pageBreakPlugin, placeholderPlugin, regenerateToc, registerSlashCommands, slashMenuPlugin, slashState, tablePlugin, textColorPlugin, tocPlugin };
|
|
267
|
+
export { AIExtension, type AIPreviewState, BibliographyNode, CitationEngineExtension, CitationNode, CiteEngine, type CommentMarkAttrs, CommentMark as CommentMarkExtension, DateChipNode, DropdownChipNode, FileChipNode, FootnoteNode, LocationChipNode, PageBreak, PeopleChipNode, type PlaceholderPluginOptions, SlashMenuExtension, TocEntryNode, TocNode, TocPageNumNode, aiPlugin, aiPluginKey, alignmentPlugin, blockquotePlugin, citationPlugin, codeBlockPlugin, collectHeadings, commentPlugin, createPlaceholderPlugin, defaultPlugins, fontSizePlugin, footnotePlugin, formattingPlugin, getAIPreview, getCitationEngine, headingsPlugin, highlightPlugin, imagePlugin, linkPlugin, listsPlugin, onSlashStateChange, pageBreakPlugin, placeholderPlugin, regenerateToc, registerSlashCommands, slashMenuPlugin, slashState, smartElementsPlugin, tablePlugin, textColorPlugin, tocPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1247,10 +1247,440 @@ var commentPlugin = {
|
|
|
1247
1247
|
commands: {}
|
|
1248
1248
|
};
|
|
1249
1249
|
|
|
1250
|
+
// src/smartElements.ts
|
|
1251
|
+
import { Node as Node5, mergeAttributes as mergeAttributes6 } from "@tiptap/core";
|
|
1252
|
+
import { definePlugin as definePlugin18 } from "@kedataindo/docflow-core";
|
|
1253
|
+
function todayISO() {
|
|
1254
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1255
|
+
}
|
|
1256
|
+
function formatDate(iso) {
|
|
1257
|
+
if (!iso) return "Pick a date";
|
|
1258
|
+
const d = /* @__PURE__ */ new Date(iso + "T00:00:00");
|
|
1259
|
+
if (isNaN(d.getTime())) return "Pick a date";
|
|
1260
|
+
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
|
|
1261
|
+
}
|
|
1262
|
+
function initialOf(name) {
|
|
1263
|
+
return (name || "?").trim().charAt(0).toUpperCase() || "?";
|
|
1264
|
+
}
|
|
1265
|
+
var DEFAULT_STATUSES = ["To Do", "In Progress", "Review", "Approved"];
|
|
1266
|
+
function slugify(s) {
|
|
1267
|
+
return s.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
1268
|
+
}
|
|
1269
|
+
var DateChipNode = Node5.create({
|
|
1270
|
+
name: "dateChip",
|
|
1271
|
+
group: "inline",
|
|
1272
|
+
inline: true,
|
|
1273
|
+
selectable: true,
|
|
1274
|
+
draggable: false,
|
|
1275
|
+
atom: true,
|
|
1276
|
+
addAttributes() {
|
|
1277
|
+
return {
|
|
1278
|
+
date: {
|
|
1279
|
+
default: todayISO(),
|
|
1280
|
+
parseHTML: (el) => el.getAttribute("data-date") ?? todayISO(),
|
|
1281
|
+
renderHTML: (attrs) => ({ "data-date": attrs.date ?? "" })
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
},
|
|
1285
|
+
parseHTML() {
|
|
1286
|
+
return [{ tag: 'span[data-node-type="date-chip"]' }];
|
|
1287
|
+
},
|
|
1288
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1289
|
+
return ["span", mergeAttributes6(HTMLAttributes, {
|
|
1290
|
+
"data-node-type": "date-chip",
|
|
1291
|
+
class: "docs-chip docs-chip--date"
|
|
1292
|
+
}), formatDate(node.attrs.date)];
|
|
1293
|
+
},
|
|
1294
|
+
addNodeView() {
|
|
1295
|
+
return (props) => {
|
|
1296
|
+
let currentNode = props.node;
|
|
1297
|
+
const getPos = props.getPos;
|
|
1298
|
+
const view = props.view;
|
|
1299
|
+
const dom = document.createElement("span");
|
|
1300
|
+
dom.className = "docs-chip docs-chip--date";
|
|
1301
|
+
dom.setAttribute("data-node-type", "date-chip");
|
|
1302
|
+
dom.setAttribute("contenteditable", "false");
|
|
1303
|
+
const render = () => {
|
|
1304
|
+
if (dom.querySelector("input")) return;
|
|
1305
|
+
dom.textContent = formatDate(currentNode.attrs.date);
|
|
1306
|
+
dom.setAttribute("data-date", currentNode.attrs.date);
|
|
1307
|
+
};
|
|
1308
|
+
render();
|
|
1309
|
+
dom.addEventListener("click", (e) => {
|
|
1310
|
+
e.preventDefault();
|
|
1311
|
+
e.stopPropagation();
|
|
1312
|
+
if (dom.querySelector("input")) return;
|
|
1313
|
+
const input = document.createElement("input");
|
|
1314
|
+
input.type = "date";
|
|
1315
|
+
input.value = currentNode.attrs.date;
|
|
1316
|
+
input.className = "docs-chip-date-input";
|
|
1317
|
+
dom.replaceChildren(input);
|
|
1318
|
+
input.focus();
|
|
1319
|
+
const commit = () => {
|
|
1320
|
+
const newVal = input.value;
|
|
1321
|
+
const pos = getPos();
|
|
1322
|
+
if (typeof pos === "number") {
|
|
1323
|
+
view.dispatch(view.state.tr.setNodeMarkup(pos, void 0, { date: newVal }));
|
|
1324
|
+
}
|
|
1325
|
+
setTimeout(render, 30);
|
|
1326
|
+
};
|
|
1327
|
+
input.addEventListener("change", commit);
|
|
1328
|
+
input.addEventListener("blur", () => setTimeout(render, 30));
|
|
1329
|
+
});
|
|
1330
|
+
return {
|
|
1331
|
+
dom,
|
|
1332
|
+
update(updatedNode) {
|
|
1333
|
+
if (updatedNode.type.name !== "dateChip") return false;
|
|
1334
|
+
currentNode = updatedNode;
|
|
1335
|
+
render();
|
|
1336
|
+
return true;
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
var PeopleChipNode = Node5.create({
|
|
1343
|
+
name: "peopleChip",
|
|
1344
|
+
group: "inline",
|
|
1345
|
+
inline: true,
|
|
1346
|
+
selectable: true,
|
|
1347
|
+
draggable: false,
|
|
1348
|
+
atom: true,
|
|
1349
|
+
addAttributes() {
|
|
1350
|
+
return {
|
|
1351
|
+
userId: {
|
|
1352
|
+
default: "",
|
|
1353
|
+
parseHTML: (el) => el.getAttribute("data-user-id") ?? "",
|
|
1354
|
+
renderHTML: (attrs) => attrs.userId ? { "data-user-id": attrs.userId } : {}
|
|
1355
|
+
},
|
|
1356
|
+
name: {
|
|
1357
|
+
default: "",
|
|
1358
|
+
parseHTML: (el) => el.getAttribute("data-name") ?? "",
|
|
1359
|
+
renderHTML: (attrs) => ({ "data-name": attrs.name ?? "" })
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
},
|
|
1363
|
+
parseHTML() {
|
|
1364
|
+
return [{ tag: 'span[data-node-type="people-chip"]' }];
|
|
1365
|
+
},
|
|
1366
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1367
|
+
return ["span", mergeAttributes6(HTMLAttributes, {
|
|
1368
|
+
"data-node-type": "people-chip",
|
|
1369
|
+
class: "docs-chip docs-chip--people"
|
|
1370
|
+
}), `@${node.attrs.name || "user"}`];
|
|
1371
|
+
},
|
|
1372
|
+
addNodeView() {
|
|
1373
|
+
return (props) => {
|
|
1374
|
+
let currentNode = props.node;
|
|
1375
|
+
const dom = document.createElement("span");
|
|
1376
|
+
dom.className = "docs-chip docs-chip--people";
|
|
1377
|
+
dom.setAttribute("data-node-type", "people-chip");
|
|
1378
|
+
dom.setAttribute("contenteditable", "false");
|
|
1379
|
+
const render = () => {
|
|
1380
|
+
const name = currentNode.attrs.name || "user";
|
|
1381
|
+
dom.innerHTML = "";
|
|
1382
|
+
const avatar = document.createElement("span");
|
|
1383
|
+
avatar.className = "docs-chip-avatar";
|
|
1384
|
+
avatar.textContent = initialOf(name);
|
|
1385
|
+
dom.appendChild(avatar);
|
|
1386
|
+
const label = document.createElement("span");
|
|
1387
|
+
label.className = "docs-chip-label";
|
|
1388
|
+
label.textContent = "@" + name;
|
|
1389
|
+
dom.appendChild(label);
|
|
1390
|
+
};
|
|
1391
|
+
render();
|
|
1392
|
+
return {
|
|
1393
|
+
dom,
|
|
1394
|
+
update(updatedNode) {
|
|
1395
|
+
if (updatedNode.type.name !== "peopleChip") return false;
|
|
1396
|
+
currentNode = updatedNode;
|
|
1397
|
+
render();
|
|
1398
|
+
return true;
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
var FileChipNode = Node5.create({
|
|
1405
|
+
name: "fileChip",
|
|
1406
|
+
group: "inline",
|
|
1407
|
+
inline: true,
|
|
1408
|
+
selectable: true,
|
|
1409
|
+
draggable: false,
|
|
1410
|
+
atom: true,
|
|
1411
|
+
addAttributes() {
|
|
1412
|
+
return {
|
|
1413
|
+
fileId: {
|
|
1414
|
+
default: "",
|
|
1415
|
+
parseHTML: (el) => el.getAttribute("data-file-id") ?? "",
|
|
1416
|
+
renderHTML: (attrs) => attrs.fileId ? { "data-file-id": attrs.fileId } : {}
|
|
1417
|
+
},
|
|
1418
|
+
name: {
|
|
1419
|
+
default: "",
|
|
1420
|
+
parseHTML: (el) => el.getAttribute("data-name") ?? "",
|
|
1421
|
+
renderHTML: (attrs) => ({ "data-name": attrs.name ?? "" })
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
},
|
|
1425
|
+
parseHTML() {
|
|
1426
|
+
return [{ tag: 'span[data-node-type="file-chip"]' }];
|
|
1427
|
+
},
|
|
1428
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1429
|
+
return ["span", mergeAttributes6(HTMLAttributes, {
|
|
1430
|
+
"data-node-type": "file-chip",
|
|
1431
|
+
class: "docs-chip docs-chip--file"
|
|
1432
|
+
}), node.attrs.name || "file"];
|
|
1433
|
+
},
|
|
1434
|
+
addNodeView() {
|
|
1435
|
+
return (props) => {
|
|
1436
|
+
let currentNode = props.node;
|
|
1437
|
+
const dom = document.createElement("span");
|
|
1438
|
+
dom.className = "docs-chip docs-chip--file";
|
|
1439
|
+
dom.setAttribute("data-node-type", "file-chip");
|
|
1440
|
+
dom.setAttribute("contenteditable", "false");
|
|
1441
|
+
const render = () => {
|
|
1442
|
+
const name = currentNode.attrs.name || "Untitled file";
|
|
1443
|
+
dom.innerHTML = "";
|
|
1444
|
+
const icon = document.createElement("span");
|
|
1445
|
+
icon.className = "docs-chip-icon";
|
|
1446
|
+
icon.textContent = "\u{1F5CE}";
|
|
1447
|
+
dom.appendChild(icon);
|
|
1448
|
+
const label = document.createElement("span");
|
|
1449
|
+
label.className = "docs-chip-label";
|
|
1450
|
+
label.textContent = name;
|
|
1451
|
+
dom.appendChild(label);
|
|
1452
|
+
};
|
|
1453
|
+
render();
|
|
1454
|
+
return {
|
|
1455
|
+
dom,
|
|
1456
|
+
update(updatedNode) {
|
|
1457
|
+
if (updatedNode.type.name !== "fileChip") return false;
|
|
1458
|
+
currentNode = updatedNode;
|
|
1459
|
+
render();
|
|
1460
|
+
return true;
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
1466
|
+
var DropdownChipNode = Node5.create({
|
|
1467
|
+
name: "dropdownChip",
|
|
1468
|
+
group: "inline",
|
|
1469
|
+
inline: true,
|
|
1470
|
+
selectable: true,
|
|
1471
|
+
draggable: false,
|
|
1472
|
+
atom: true,
|
|
1473
|
+
addAttributes() {
|
|
1474
|
+
return {
|
|
1475
|
+
options: {
|
|
1476
|
+
default: DEFAULT_STATUSES,
|
|
1477
|
+
parseHTML: (el) => {
|
|
1478
|
+
const raw = el.getAttribute("data-options") ?? "";
|
|
1479
|
+
const list = raw ? raw.split("|") : [];
|
|
1480
|
+
return list.length ? list : DEFAULT_STATUSES;
|
|
1481
|
+
},
|
|
1482
|
+
renderHTML: (attrs) => ({
|
|
1483
|
+
"data-options": (attrs.options ?? []).join("|")
|
|
1484
|
+
})
|
|
1485
|
+
},
|
|
1486
|
+
selected: {
|
|
1487
|
+
default: DEFAULT_STATUSES[0],
|
|
1488
|
+
parseHTML: (el) => el.getAttribute("data-selected") ?? DEFAULT_STATUSES[0],
|
|
1489
|
+
renderHTML: (attrs) => ({ "data-selected": attrs.selected ?? "" })
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
},
|
|
1493
|
+
parseHTML() {
|
|
1494
|
+
return [{ tag: 'span[data-node-type="dropdown-chip"]' }];
|
|
1495
|
+
},
|
|
1496
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1497
|
+
return ["span", mergeAttributes6(HTMLAttributes, {
|
|
1498
|
+
"data-node-type": "dropdown-chip",
|
|
1499
|
+
class: "docs-chip docs-chip--dropdown"
|
|
1500
|
+
}), node.attrs.selected || ""];
|
|
1501
|
+
},
|
|
1502
|
+
addNodeView() {
|
|
1503
|
+
return (props) => {
|
|
1504
|
+
let currentNode = props.node;
|
|
1505
|
+
const getPos = props.getPos;
|
|
1506
|
+
const view = props.view;
|
|
1507
|
+
const dom = document.createElement("span");
|
|
1508
|
+
dom.className = "docs-chip docs-chip--dropdown";
|
|
1509
|
+
dom.setAttribute("data-node-type", "dropdown-chip");
|
|
1510
|
+
dom.setAttribute("contenteditable", "false");
|
|
1511
|
+
const render = () => {
|
|
1512
|
+
const opts = currentNode.attrs.options ?? DEFAULT_STATUSES;
|
|
1513
|
+
const sel = currentNode.attrs.selected ?? (opts[0] ?? "");
|
|
1514
|
+
dom.innerHTML = "";
|
|
1515
|
+
const select = document.createElement("select");
|
|
1516
|
+
select.className = "docs-chip-select";
|
|
1517
|
+
select.addEventListener("mousedown", (e) => e.stopPropagation());
|
|
1518
|
+
for (const opt of opts) {
|
|
1519
|
+
const o = document.createElement("option");
|
|
1520
|
+
o.value = opt;
|
|
1521
|
+
o.textContent = opt;
|
|
1522
|
+
if (opt === sel) o.selected = true;
|
|
1523
|
+
select.appendChild(o);
|
|
1524
|
+
}
|
|
1525
|
+
select.addEventListener("change", () => {
|
|
1526
|
+
const pos = getPos();
|
|
1527
|
+
if (typeof pos === "number") {
|
|
1528
|
+
view.dispatch(view.state.tr.setNodeMarkup(pos, void 0, {
|
|
1529
|
+
...currentNode.attrs,
|
|
1530
|
+
selected: select.value
|
|
1531
|
+
}));
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
dom.appendChild(select);
|
|
1535
|
+
};
|
|
1536
|
+
render();
|
|
1537
|
+
return {
|
|
1538
|
+
dom,
|
|
1539
|
+
update(updatedNode) {
|
|
1540
|
+
if (updatedNode.type.name !== "dropdownChip") return false;
|
|
1541
|
+
currentNode = updatedNode;
|
|
1542
|
+
render();
|
|
1543
|
+
return true;
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
var LocationChipNode = Node5.create({
|
|
1550
|
+
name: "locationChip",
|
|
1551
|
+
group: "inline",
|
|
1552
|
+
inline: true,
|
|
1553
|
+
selectable: true,
|
|
1554
|
+
draggable: false,
|
|
1555
|
+
atom: true,
|
|
1556
|
+
addAttributes() {
|
|
1557
|
+
return {
|
|
1558
|
+
label: {
|
|
1559
|
+
default: "",
|
|
1560
|
+
parseHTML: (el) => el.getAttribute("data-label") ?? "",
|
|
1561
|
+
renderHTML: (attrs) => ({ "data-label": attrs.label ?? "" })
|
|
1562
|
+
},
|
|
1563
|
+
lat: {
|
|
1564
|
+
default: null,
|
|
1565
|
+
parseHTML: (el) => {
|
|
1566
|
+
const v = el.getAttribute("data-lat");
|
|
1567
|
+
return v === null ? null : Number(v);
|
|
1568
|
+
},
|
|
1569
|
+
renderHTML: (attrs) => attrs.lat != null ? { "data-lat": attrs.lat } : {}
|
|
1570
|
+
},
|
|
1571
|
+
lng: {
|
|
1572
|
+
default: null,
|
|
1573
|
+
parseHTML: (el) => {
|
|
1574
|
+
const v = el.getAttribute("data-lng");
|
|
1575
|
+
return v === null ? null : Number(v);
|
|
1576
|
+
},
|
|
1577
|
+
renderHTML: (attrs) => attrs.lng != null ? { "data-lng": attrs.lng } : {}
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
},
|
|
1581
|
+
parseHTML() {
|
|
1582
|
+
return [{ tag: 'span[data-node-type="location-chip"]' }];
|
|
1583
|
+
},
|
|
1584
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
1585
|
+
return ["span", mergeAttributes6(HTMLAttributes, {
|
|
1586
|
+
"data-node-type": "location-chip",
|
|
1587
|
+
class: "docs-chip docs-chip--location"
|
|
1588
|
+
}), node.attrs.label || ""];
|
|
1589
|
+
},
|
|
1590
|
+
addNodeView() {
|
|
1591
|
+
return (props) => {
|
|
1592
|
+
let currentNode = props.node;
|
|
1593
|
+
const dom = document.createElement("span");
|
|
1594
|
+
dom.className = "docs-chip docs-chip--location";
|
|
1595
|
+
dom.setAttribute("data-node-type", "location-chip");
|
|
1596
|
+
dom.setAttribute("contenteditable", "false");
|
|
1597
|
+
const render = () => {
|
|
1598
|
+
const label = currentNode.attrs.label || "Add location";
|
|
1599
|
+
dom.innerHTML = "";
|
|
1600
|
+
const icon = document.createElement("span");
|
|
1601
|
+
icon.className = "docs-chip-icon";
|
|
1602
|
+
icon.textContent = "\u{1F4CD}";
|
|
1603
|
+
dom.appendChild(icon);
|
|
1604
|
+
const lbl = document.createElement("span");
|
|
1605
|
+
lbl.className = "docs-chip-label";
|
|
1606
|
+
lbl.textContent = label;
|
|
1607
|
+
dom.appendChild(lbl);
|
|
1608
|
+
};
|
|
1609
|
+
render();
|
|
1610
|
+
return {
|
|
1611
|
+
dom,
|
|
1612
|
+
update(updatedNode) {
|
|
1613
|
+
if (updatedNode.type.name !== "locationChip") return false;
|
|
1614
|
+
currentNode = updatedNode;
|
|
1615
|
+
render();
|
|
1616
|
+
return true;
|
|
1617
|
+
}
|
|
1618
|
+
};
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
});
|
|
1622
|
+
var smartElementsPlugin = definePlugin18({
|
|
1623
|
+
id: "smart-elements",
|
|
1624
|
+
tiptapExtensions: [
|
|
1625
|
+
DateChipNode,
|
|
1626
|
+
PeopleChipNode,
|
|
1627
|
+
FileChipNode,
|
|
1628
|
+
DropdownChipNode,
|
|
1629
|
+
LocationChipNode
|
|
1630
|
+
],
|
|
1631
|
+
slashCommands: [
|
|
1632
|
+
{ name: "Date", command: "insertDateChip" },
|
|
1633
|
+
{ name: "People", command: "insertPeopleChip" },
|
|
1634
|
+
{ name: "File", command: "insertFileChip" },
|
|
1635
|
+
{ name: "Dropdown", command: "insertDropdownChip" },
|
|
1636
|
+
{ name: "Location", command: "insertLocationChip" }
|
|
1637
|
+
],
|
|
1638
|
+
commands: {
|
|
1639
|
+
insertDateChip: (editor) => {
|
|
1640
|
+
return editor.chain().focus().insertContent({
|
|
1641
|
+
type: "dateChip",
|
|
1642
|
+
attrs: { date: todayISO() }
|
|
1643
|
+
}).run();
|
|
1644
|
+
},
|
|
1645
|
+
insertPeopleChip: (editor) => {
|
|
1646
|
+
const name = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter user name:", "") ?? "" : "";
|
|
1647
|
+
if (!name.trim()) return false;
|
|
1648
|
+
const trimmed = name.trim();
|
|
1649
|
+
return editor.chain().focus().insertContent({
|
|
1650
|
+
type: "peopleChip",
|
|
1651
|
+
attrs: { userId: slugify(trimmed), name: trimmed }
|
|
1652
|
+
}).run();
|
|
1653
|
+
},
|
|
1654
|
+
insertFileChip: (editor) => {
|
|
1655
|
+
const name = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter file/document name:", "") ?? "" : "";
|
|
1656
|
+
if (!name.trim()) return false;
|
|
1657
|
+
const trimmed = name.trim();
|
|
1658
|
+
return editor.chain().focus().insertContent({
|
|
1659
|
+
type: "fileChip",
|
|
1660
|
+
attrs: { fileId: slugify(trimmed), name: trimmed }
|
|
1661
|
+
}).run();
|
|
1662
|
+
},
|
|
1663
|
+
insertDropdownChip: (editor) => {
|
|
1664
|
+
return editor.chain().focus().insertContent({
|
|
1665
|
+
type: "dropdownChip",
|
|
1666
|
+
attrs: { options: DEFAULT_STATUSES, selected: DEFAULT_STATUSES[0] }
|
|
1667
|
+
}).run();
|
|
1668
|
+
},
|
|
1669
|
+
insertLocationChip: (editor) => {
|
|
1670
|
+
const label = typeof window !== "undefined" && typeof window.prompt === "function" ? window.prompt("Enter location name:", "") ?? "" : "";
|
|
1671
|
+
if (!label.trim()) return false;
|
|
1672
|
+
return editor.chain().focus().insertContent({
|
|
1673
|
+
type: "locationChip",
|
|
1674
|
+
attrs: { label: label.trim() }
|
|
1675
|
+
}).run();
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
|
|
1250
1680
|
// src/slashMenu.ts
|
|
1251
1681
|
import { Extension as Extension3 } from "@tiptap/core";
|
|
1252
1682
|
import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
1253
|
-
import { definePlugin as
|
|
1683
|
+
import { definePlugin as definePlugin19 } from "@kedataindo/docflow-core";
|
|
1254
1684
|
var slashState = {
|
|
1255
1685
|
open: false,
|
|
1256
1686
|
query: "",
|
|
@@ -1395,7 +1825,7 @@ var SlashMenuExtension = Extension3.create({
|
|
|
1395
1825
|
];
|
|
1396
1826
|
}
|
|
1397
1827
|
});
|
|
1398
|
-
var slashMenuPlugin =
|
|
1828
|
+
var slashMenuPlugin = definePlugin19({
|
|
1399
1829
|
id: "slash-menu",
|
|
1400
1830
|
tiptapExtensions: [SlashMenuExtension],
|
|
1401
1831
|
hooks: {
|
|
@@ -1426,7 +1856,8 @@ var defaultPlugins = [
|
|
|
1426
1856
|
highlightPlugin,
|
|
1427
1857
|
citationPlugin,
|
|
1428
1858
|
aiPlugin,
|
|
1429
|
-
commentPlugin
|
|
1859
|
+
commentPlugin,
|
|
1860
|
+
smartElementsPlugin
|
|
1430
1861
|
];
|
|
1431
1862
|
export {
|
|
1432
1863
|
AIExtension,
|
|
@@ -1438,9 +1869,14 @@ export {
|
|
|
1438
1869
|
CiteEngine,
|
|
1439
1870
|
CommentMark as CommentMarkExtension,
|
|
1440
1871
|
DEFAULT_CSL_STYLE,
|
|
1872
|
+
DateChipNode,
|
|
1873
|
+
DropdownChipNode,
|
|
1874
|
+
FileChipNode,
|
|
1441
1875
|
FontSizeExtension,
|
|
1442
1876
|
FootnoteNode,
|
|
1877
|
+
LocationChipNode,
|
|
1443
1878
|
PageBreak,
|
|
1879
|
+
PeopleChipNode,
|
|
1444
1880
|
SlashMenuExtension,
|
|
1445
1881
|
TocEntryNode,
|
|
1446
1882
|
TocNode,
|
|
@@ -1475,6 +1911,7 @@ export {
|
|
|
1475
1911
|
sanitizeCiteprocHtml,
|
|
1476
1912
|
slashMenuPlugin,
|
|
1477
1913
|
slashState,
|
|
1914
|
+
smartElementsPlugin,
|
|
1478
1915
|
tablePlugin,
|
|
1479
1916
|
textColorPlugin,
|
|
1480
1917
|
tocPlugin
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kedataindo/docflow-plugins",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.32",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@tiptap/extension-highlight": "^2.27.2",
|
|
31
31
|
"@tiptap/pm": "^2.11.0",
|
|
32
32
|
"citeproc": "^2.4.63",
|
|
33
|
-
"@kedataindo/docflow-core": "0.0.
|
|
33
|
+
"@kedataindo/docflow-core": "0.0.30"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@tiptap/core": "^2.11.0",
|