@code0-tech/pictor 0.10.8 → 0.11.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.
@@ -1 +1 @@
1
- .editor-input{width:100%;flex:1 1 auto;overflow:hidden;padding:.59rem 0;position:relative;align-self:stretch}.editor-input .cm-editor{height:100%;outline:none!important}.editor-input .cm-content{padding:0;position:relative}.editor-input .cm-line{align-self:stretch;padding-left:0}.editor-input .cm-cursor{border-width:2px;border-radius:50rem;border-color:#fff}
1
+ .input-wrapper__control--single-line{white-space:pre!important;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.input-wrapper__control--single-line::-webkit-scrollbar{display:none}.editor-input__menu-anchor{position:absolute;left:0;top:0;width:0;height:0;opacity:0;pointer-events:none}.editor-input{width:100%;overflow:hidden;position:relative;align-self:stretch;font-family:Inter,sans-serif;font-size:.8rem;letter-spacing:-.5px;font-weight:400;color:#ffffffbf}.editor-input [data-slate-editor]{flex:1 1 auto;padding:.6rem 0;align-self:stretch;outline:none;caret-color:#fff;min-height:1.2em;white-space:pre-wrap;word-break:break-word}.editor-input [data-slate-node=element]{margin:0;padding:0}.editor-input ::selection{background:#70b3ff40}.editor-input [data-slate-placeholder]{color:#ffffff4d;pointer-events:none;-webkit-user-select:none;user-select:none}
@@ -1,32 +1,32 @@
1
- import { jsx as R } from "react/jsx-runtime";
2
- import { c as h } from "../../_virtual/compiler-runtime.js";
1
+ import { jsx as h } from "react/jsx-runtime";
2
+ import { c as y } from "../../_virtual/compiler-runtime.js";
3
3
  import '../../assets/components/button/Button.style.css';/* empty css */
4
4
  import z from "react";
5
5
  import "../../utils/contextStore.js";
6
6
  import { mergeComponentProps as S } from "../../utils/component.js";
7
7
  import "js-md5";
8
- const P = z.forwardRef((a, d) => {
9
- const t = h.c(11);
10
- let o, n, e, i;
11
- if (t[0] !== a || t[1] !== d) {
8
+ const k = z.forwardRef((d, l) => {
9
+ const t = y.c(13);
10
+ let o, r, e, i, n;
11
+ if (t[0] !== d || t[1] !== l) {
12
12
  const {
13
- children: f,
14
- variant: l,
15
- color: c,
16
- paddingSize: m,
17
- active: u,
18
- disabled: b,
19
- ...p
20
- } = a;
21
- o = f;
22
- const v = l === void 0 ? "normal" : l, $ = c === void 0 ? "secondary" : c, g = m === void 0 ? "xs" : m, x = u === void 0 ? !1 : u;
23
- n = b === void 0 ? !1 : b, e = d, i = S(`button button--${$} ${x ? "button--active" : ""} ${n ? "button--disabled" : ""} button--${v} button--${g}`, p), t[0] = a, t[1] = d, t[2] = o, t[3] = n, t[4] = e, t[5] = i;
13
+ children: p,
14
+ variant: c,
15
+ color: m,
16
+ paddingSize: u,
17
+ active: b,
18
+ disabled: f,
19
+ ...v
20
+ } = d;
21
+ o = p;
22
+ const $ = c === void 0 ? "normal" : c, g = m === void 0 ? "secondary" : m, x = u === void 0 ? "xs" : u, R = b === void 0 ? !1 : b;
23
+ r = f === void 0 ? !1 : f, e = l, i = "button", n = S(`button button--${g} ${R ? "button--active" : ""} ${r ? "button--disabled" : ""} button--${$} button--${x}`, v), t[0] = d, t[1] = l, t[2] = o, t[3] = r, t[4] = e, t[5] = i, t[6] = n;
24
24
  } else
25
- o = t[2], n = t[3], e = t[4], i = t[5];
26
- const s = n ? "true" : "false";
27
- let r;
28
- return t[6] !== o || t[7] !== e || t[8] !== i || t[9] !== s ? (r = /* @__PURE__ */ R("button", { ref: e, ...i, "aria-disabled": s, children: o }), t[6] = o, t[7] = e, t[8] = i, t[9] = s, t[10] = r) : r = t[10], r;
25
+ o = t[2], r = t[3], e = t[4], i = t[5], n = t[6];
26
+ const s = r ? "true" : "false";
27
+ let a;
28
+ return t[7] !== o || t[8] !== e || t[9] !== i || t[10] !== n || t[11] !== s ? (a = /* @__PURE__ */ h("button", { ref: e, type: i, ...n, "aria-disabled": s, children: o }), t[7] = o, t[8] = e, t[9] = i, t[10] = n, t[11] = s, t[12] = a) : a = t[12], a;
29
29
  });
30
30
  export {
31
- P as Button
31
+ k as Button
32
32
  };
@@ -1,16 +1,27 @@
1
1
  import { default as React } from 'react';
2
2
  import { ValidationProps } from './useForm';
3
3
  import { InputWrapperProps } from './InputWrapper';
4
- import { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
5
- import { Extension } from '@uiw/react-codemirror';
6
- import { StreamLanguage, TagStyle } from '@codemirror/language';
7
- export interface EditorInputProps extends Omit<InputWrapperProps, 'onChange'>, ValidationProps<any> {
8
- language?: StreamLanguage<unknown>;
9
- suggestions?: (context: CompletionContext) => CompletionResult;
10
- extensions?: Extension[];
4
+ import { InputSuggestion } from './InputSuggestion';
5
+ export interface EditorTokenRule {
6
+ pattern: RegExp;
7
+ /**
8
+ * Wrap a matched token. `children` is Slate's leaf content — include it
9
+ * somewhere so cursor positioning stays accurate.
10
+ */
11
+ wrap?: (matchedText: string, children: React.ReactNode, match: RegExpExecArray) => React.ReactNode;
12
+ style?: React.CSSProperties;
13
+ className?: string;
14
+ }
15
+ export interface EditorInputProps extends Omit<InputWrapperProps, "onChange">, ValidationProps<any> {
16
+ tokenRules?: EditorTokenRule[];
17
+ suggestions?: InputSuggestion[];
18
+ suggestionsEmptyState?: React.ReactNode;
19
+ onSuggestionSelect?: (suggestion: InputSuggestion) => void;
11
20
  disabled?: boolean;
12
21
  readonly?: boolean;
13
- tokenStyles?: TagStyle[];
22
+ /** Render as a single-line input: Enter is blocked, newlines in pasted or external values become spaces. */
23
+ singleLine?: boolean;
14
24
  onChange?: (value: string) => void;
25
+ placeholder?: string;
15
26
  }
16
27
  export declare const EditorInput: React.FC<EditorInputProps>;
@@ -1,78 +1,170 @@
1
- import { jsx as c } from "react/jsx-runtime";
2
- import e from "react";
3
- import { InputWrapper as N } from "./InputWrapper.js";
4
- import x from "@uiw/react-codemirror";
5
- import { createTheme as p } from "@uiw/codemirror-themes";
6
- import { tags as t } from "../../node_modules/@lezer/highlight/dist/index.js";
1
+ import { jsx as i, jsxs as P } from "react/jsx-runtime";
2
+ import R, { useMemo as O, useRef as w, useCallback as f, useState as le } from "react";
3
+ import { createEditor as se, Editor as k, Transforms as D, Text as ae, Node as ce } from "slate";
4
+ import { withReact as ue, ReactEditor as pe, Editable as fe, Slate as de } from "slate-react";
5
+ import { withHistory as ge } from "slate-history";
6
+ import { InputWrapper as he } from "./InputWrapper.js";
7
7
  import "../../utils/contextStore.js";
8
- import { mergeComponentProps as B } from "../../utils/component.js";
9
- import { hashToColor as r } from "../../utils/color.js";
8
+ import { mergeComponentProps as me } from "../../utils/component.js";
9
+ import "js-md5";
10
+ import { Menu as xe, MenuTrigger as ye, MenuPortal as we } from "../menu/Menu.js";
11
+ import { InputSuggestionMenuContent as Te, InputSuggestionMenuContentItems as ve } from "./InputSuggestion.js";
10
12
  import '../../assets/components/form/EditorInput.style.css';/* empty css */
11
- const A = [], L = [], P = {
12
- lineNumbers: !1,
13
- foldGutter: !1,
14
- highlightActiveLine: !1,
15
- highlightActiveLineGutter: !1
16
- }, u = {
17
- background: "transparent",
18
- backgroundImage: "",
19
- foreground: "rgba(255,255,255, 0.75)",
20
- caret: "gray",
21
- selection: "rgba(112,179,255,0.25)",
22
- selectionMatch: "rgba(112,179,255,0.1)",
23
- fontSize: "0.8rem",
24
- fontFamily: '"Inter", sans-serif',
25
- letterSpacing: "-0.5px",
26
- fontWeight: "400",
27
- gutterBackground: "transparent",
28
- gutterForeground: "rgba(255,255,255, 0.5)",
29
- gutterBorder: "transparent",
30
- gutterActiveForeground: "rgba(255,255,255, 1)",
31
- lineHighlight: "rgba(255,255,255, 0.1)"
32
- }, h = [{
33
- tag: t.squareBracket,
34
- color: r("squareBracket")
35
- }, {
36
- tag: t.bracket,
37
- color: r("bracket")
38
- }, {
39
- tag: t.string,
40
- color: r("Text")
41
- }, {
42
- tag: t.bool,
43
- color: r("Boolean")
44
- }, {
45
- tag: t.number,
46
- color: r("Number")
47
- }], F = p({
48
- theme: "light",
49
- settings: u,
50
- styles: h
51
- }), Y = e.memo((f) => {
13
+ const B = (g) => (g || "").split(`
14
+ `).map((h) => ({
15
+ type: "paragraph",
16
+ children: [{
17
+ text: h
18
+ }]
19
+ })), F = (g) => g.map((h) => ce.string(h)).join(`
20
+ `), Oe = R.memo((g) => {
52
21
  const {
53
- title: d,
54
- right: T,
55
- left: b,
56
- rightType: E,
57
- leftType: S,
58
- language: o,
59
- description: _,
60
- extensions: n = A,
61
- tokenStyles: a = L,
62
- formValidation: i,
63
- onChange: g,
64
- wrapperComponent: k,
65
- ...l
66
- } = f, y = e.useMemo(() => [...o ? [...n, o] : n], [n, o]), C = e.useMemo(() => a.length === 0 ? F : p({
67
- theme: "light",
68
- settings: u,
69
- styles: [...h, ...a]
70
- }), [a]), m = i?.setValue, M = e.useCallback((s) => {
71
- m?.(s), g?.(s);
72
- }, [m, g]), I = e.useMemo(() => B("editor-input", l), [l]);
73
- return /* @__PURE__ */ c(N, { title: d, description: _, right: T, left: b, rightType: E, leftType: S, formValidation: i, wrapperComponent: k, children: /* @__PURE__ */ c(x, { extensions: y, onChange: M, theme: C, indentWithTab: !1, ...I, basicSetup: P }) });
22
+ title: h,
23
+ right: j,
24
+ left: A,
25
+ rightType: H,
26
+ leftType: K,
27
+ description: $,
28
+ wrapperComponent: v,
29
+ tokenRules: m = [],
30
+ suggestions: s,
31
+ suggestionsEmptyState: L,
32
+ onSuggestionSelect: q,
33
+ formValidation: E,
34
+ onChange: I,
35
+ disabled: z = !1,
36
+ readonly: U = !1,
37
+ singleLine: x = !1,
38
+ placeholder: W,
39
+ value: G,
40
+ initialValue: J,
41
+ defaultValue: Q,
42
+ required: Ce,
43
+ ...X
44
+ } = g, S = String(G ?? J ?? Q ?? ""), c = x ? S.replace(/\n/g, " ") : S, r = O(() => ge(ue(se())), []), Y = O(() => B(c), []), T = w(c);
45
+ R.useEffect(() => {
46
+ if (c === T.current || (T.current = c, F(r.children) === c)) return;
47
+ const e = B(c);
48
+ k.withoutNormalizing(r, () => {
49
+ for (D.delete(r, {
50
+ at: {
51
+ anchor: k.start(r, []),
52
+ focus: k.end(r, [])
53
+ }
54
+ }), D.insertNodes(r, e, {
55
+ at: [0]
56
+ }); r.children.length > e.length; ) D.removeNodes(r, {
57
+ at: [r.children.length - 1]
58
+ });
59
+ });
60
+ }, [c, r]);
61
+ const Z = f(([e, t]) => {
62
+ const l = [];
63
+ if (!ae.isText(e) || !m.length) return l;
64
+ const {
65
+ text: n
66
+ } = e;
67
+ return m.forEach((o, oe) => {
68
+ const ie = new RegExp(o.pattern.source, o.pattern.flags.includes("g") ? o.pattern.flags : o.pattern.flags + "g");
69
+ let p;
70
+ for (; (p = ie.exec(n)) !== null && p[0].length; )
71
+ l.push({
72
+ anchor: {
73
+ path: t,
74
+ offset: p.index
75
+ },
76
+ focus: {
77
+ path: t,
78
+ offset: p.index + p[0].length
79
+ },
80
+ tokenRuleIndex: oe,
81
+ tokenText: p[0],
82
+ tokenMatch: p
83
+ });
84
+ }), l;
85
+ }, [m]), ee = f(({
86
+ attributes: e,
87
+ children: t,
88
+ leaf: l
89
+ }) => {
90
+ const n = l;
91
+ if (n.tokenRuleIndex !== void 0) {
92
+ const o = m[n.tokenRuleIndex];
93
+ if (o)
94
+ return o.wrap ? /* @__PURE__ */ i("span", { ...e, children: o.wrap(n.tokenText ?? "", t, n.tokenMatch ?? []) }) : /* @__PURE__ */ i("span", { ...e, children: /* @__PURE__ */ i("span", { style: o.style, className: o.className, children: t }) });
95
+ }
96
+ return /* @__PURE__ */ i("span", { ...e, children: t });
97
+ }, [m]), [a, d] = le(!1), M = w(null), C = w(null), _ = w(null), u = w(void 0), y = f(() => {
98
+ const e = _.current, t = C.current, l = t?.parentElement;
99
+ if (!e || !t || !l) return;
100
+ let n = null;
101
+ try {
102
+ r.selection && (n = pe.toDOMRange(r, r.selection).getBoundingClientRect());
103
+ } catch {
104
+ n = null;
105
+ }
106
+ (!n || !n.width && !n.height && !n.left && !n.top) && (n = t.getBoundingClientRect());
107
+ const o = l.getBoundingClientRect();
108
+ e.style.left = `${n.left - o.left}px`, e.style.top = `${n.top - o.top}px`, e.style.width = "0px", e.style.height = `${n.height || parseFloat(getComputedStyle(t).lineHeight) || 16}px`;
109
+ }, [r]), N = E?.setValue, te = f((e) => {
110
+ a && y();
111
+ const t = F(e);
112
+ t !== T.current && (T.current = t, N?.(t), I?.(t));
113
+ }, [a, y, N, I]), b = f(() => {
114
+ u.current && clearTimeout(u.current), s && (y(), d(!0));
115
+ }, [s, y]);
116
+ R.useEffect(() => {
117
+ a && y();
118
+ }, [a]);
119
+ const ne = f(() => {
120
+ u.current && clearTimeout(u.current), u.current = setTimeout(() => d(!1), 150);
121
+ }, []), re = f((e) => {
122
+ if (x && e.key === "Enter" && e.preventDefault(), !s) return;
123
+ const t = M.current;
124
+ if (e.ctrlKey && e.code === "Space") {
125
+ e.preventDefault(), a ? t?.focusFirstItem() : b();
126
+ return;
127
+ }
128
+ !a || !t || (e.key === "ArrowDown" ? (e.preventDefault(), t.highlightNextItem()) : e.key === "ArrowUp" ? (e.preventDefault(), t.highlightPreviousItem()) : e.key === "Enter" ? t.selectActiveItem() && (e.preventDefault(), d(!1)) : e.key === "Escape" && (e.preventDefault(), d(!1)));
129
+ }, [s, a, b, x]), V = /* @__PURE__ */ i("div", { ...me("editor-input", X), ref: C, children: /* @__PURE__ */ i(
130
+ fe,
131
+ {
132
+ className: x ? "input-wrapper__control input-wrapper__control--single-line" : "input-wrapper__control",
133
+ decorate: Z,
134
+ renderLeaf: ee,
135
+ readOnly: z || U,
136
+ spellCheck: !1,
137
+ placeholder: W,
138
+ onBlur: ne,
139
+ onFocus: () => {
140
+ u.current && clearTimeout(u.current);
141
+ },
142
+ onKeyDown: re,
143
+ onPaste: x ? (e) => {
144
+ e.preventDefault(), r.insertText(e.clipboardData.getData("text/plain").replace(/\r?\n/g, " "));
145
+ } : void 0
146
+ }
147
+ ) });
148
+ return /* @__PURE__ */ i(de, { editor: r, initialValue: Y, onChange: te, children: /* @__PURE__ */ i(he, { title: h, description: $, right: j, left: A, rightType: H, leftType: K, formValidation: E, wrapperComponent: s ? {
149
+ ...v ?? {},
150
+ style: {
151
+ position: "relative",
152
+ ...v?.style
153
+ }
154
+ } : v, children: s ? /* @__PURE__ */ P(xe, { open: a, modal: !1, onOpenChange: (e) => !e && d(!1), children: [
155
+ V,
156
+ /* @__PURE__ */ i(ye, { asChild: !0, children: /* @__PURE__ */ i("button", { ref: _, type: "button", tabIndex: -1, "aria-hidden": !0, onMouseDown: (e) => e.preventDefault(), className: "editor-input__menu-anchor" }) }),
157
+ /* @__PURE__ */ i(we, { children: /* @__PURE__ */ P(Te, { color: "primary", onInteractOutside: (e) => {
158
+ const t = e.target;
159
+ t && C.current?.contains(t) && e.preventDefault();
160
+ }, children: [
161
+ s.length === 0 && L,
162
+ /* @__PURE__ */ i(ve, { ref: M, suggestions: s, onSuggestionSelect: (e) => {
163
+ q?.(e), d(!1);
164
+ } })
165
+ ] }) })
166
+ ] }) : V }) });
74
167
  });
75
- Y.displayName = "EditorInput";
76
168
  export {
77
- Y as EditorInput
169
+ Oe as EditorInput
78
170
  };
@@ -24,4 +24,4 @@ export interface InputSuggestionMenuContentItemsHandle {
24
24
  clearActiveItem: () => void;
25
25
  }
26
26
  export declare const InputSuggestionMenuContent: React.NamedExoticComponent<InputSuggestionMenuContentProps>;
27
- export declare const InputSuggestionMenuContentItems: React.NamedExoticComponent<InputSuggestionMenuContentItemsProps>;
27
+ export declare const InputSuggestionMenuContentItems: React.NamedExoticComponent<InputSuggestionMenuContentItemsProps & React.RefAttributes<InputSuggestionMenuContentItemsHandle>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code0-tech/pictor",
3
- "version": "0.10.8",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "description": "A simple template for a custom React component library",
6
6
  "scripts": {
@@ -18,8 +18,8 @@
18
18
  "author": "CodeZero",
19
19
  "devDependencies": {
20
20
  "@ark-ui/react": "^5.36.2",
21
- "@babel/plugin-proposal-decorators": "^7.29.0",
22
- "@babel/plugin-transform-class-properties": "^7.28.6",
21
+ "@babel/plugin-proposal-decorators": "^7.29.7",
22
+ "@babel/plugin-transform-class-properties": "^7.29.7",
23
23
  "@codemirror/autocomplete": "^6.20.3",
24
24
  "@codemirror/lang-json": "^6.0.2",
25
25
  "@codemirror/language": "^6.12.3",
@@ -61,6 +61,9 @@
61
61
  "@types/react-syntax-highlighter": "^15.5.13",
62
62
  "@uiw/codemirror-themes": "^4.25.10",
63
63
  "@uiw/react-codemirror": "^4.25.10",
64
+ "slate": "^0.124.1",
65
+ "slate-history": "^0.113.1",
66
+ "slate-react": "^0.125.1",
64
67
  "@uiw/react-json-view": "^2.0.0-alpha.43",
65
68
  "@vitejs/plugin-react": "^5.2.0",
66
69
  "@vitest/browser-playwright": "^4.1.2",
@@ -85,7 +88,7 @@
85
88
  "react-zoom-pan-pinch": "^3.7.0",
86
89
  "rimraf": "^6.1.3",
87
90
  "sass": "^1.99.0",
88
- "sass-loader": "^16.0.7",
91
+ "sass-loader": "^16.0.8",
89
92
  "sonner": "^2.0.7",
90
93
  "storybook": "^10.4.2",
91
94
  "style-loader": "^4.0.0",
@@ -142,6 +145,9 @@
142
145
  "react-resizable-panels": "^4.3.1",
143
146
  "react-zoom-pan-pinch": "^3.7.0",
144
147
  "sonner": "^2.0.7",
148
+ "slate": "^0.124.0",
149
+ "slate-history": "^0.113.0",
150
+ "slate-react": "^0.125.0",
145
151
  "zustand": ">=4.3.0 <5.0.0"
146
152
  },
147
153
  "publishConfig": {