@tslite/react 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/full.cjs +1 -1
- package/dist/full.d.cts +4 -11
- package/dist/full.d.ts +4 -11
- package/dist/full.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +17 -7
- package/dist/index.d.ts +17 -7
- package/dist/index.js +1 -1
- package/dist/{useExpressionField-RmyW3D9R.d.cts → useExpressionField-Dsh6-SIB.d.cts} +59 -20
- package/dist/{useExpressionField-RmyW3D9R.d.ts → useExpressionField-Dsh6-SIB.d.ts} +59 -20
- package/package.json +6 -7
package/dist/full.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var search=require('@tslite/codemirror/search'),
|
|
1
|
+
'use strict';var search=require('@tslite/codemirror/search'),editor=require('@tslite/editor');function y(r={}){let{dark:s=true,layout:e="inline",mode:o="expression",segmenter:n="mustache",gutters:i=e==="block",search:a=e==="block",extensions:t=[]}=r;return {layout:e,mode:o,...o==="template"?{}:{segmenter:n},gutters:i,features:{chrome:{dark:s},theme:editor.tsliteTokenStyles},extensions:a?[search.searchEditing(),...t]:[...t]}}Object.defineProperty(exports,"searchEditing",{enumerable:true,get:function(){return search.searchEditing}});Object.defineProperty(exports,"tsliteTokenStyles",{enumerable:true,get:function(){return editor.tsliteTokenStyles}});exports.expressionFieldProps=y;
|
package/dist/full.d.cts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Extension } from '@codemirror/state';
|
|
2
|
-
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-
|
|
2
|
+
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-Dsh6-SIB.cjs';
|
|
3
3
|
export { searchEditing } from '@tslite/codemirror/search';
|
|
4
|
-
export { format, formatExpression } from '@tslite/format';
|
|
5
4
|
export { tsliteTokenStyles } from '@tslite/editor';
|
|
6
5
|
import 'react';
|
|
7
6
|
import '@codemirror/view';
|
|
@@ -32,12 +31,6 @@ interface PresetOptions {
|
|
|
32
31
|
/**
|
|
33
32
|
* O que o código É. Padrão: `"expression"`.
|
|
34
33
|
*
|
|
35
|
-
* Decide também qual formatador entra: um programa é reimpresso com `;` e
|
|
36
|
-
* quebra de statement; uma expressão, não. Injetar o de expressão num programa
|
|
37
|
-
* faz o `parseExpression` lançar, e o serviço então declara que não sabe
|
|
38
|
-
* formatar — em silêncio. Foi um defeito real, e é por isso que o preset
|
|
39
|
-
* escolhe por você.
|
|
40
|
-
*
|
|
41
34
|
* **`"template"`** liga o controle de fluxo (`{% if %}` / `{% for %}` /
|
|
42
35
|
* `{# #}`). Ele não é o padrão porque um `{%` literal no texto deixaria de ser
|
|
43
36
|
* texto — e num campo que hoje aceita qualquer string isso seria mudança de
|
|
@@ -62,8 +55,8 @@ interface PresetOptions {
|
|
|
62
55
|
/** Extensões suas, acrescentadas às do preset. */
|
|
63
56
|
readonly extensions?: readonly Extension[];
|
|
64
57
|
}
|
|
65
|
-
/** As props que o preset resolve — o resto (`value`, `onChange`, `
|
|
66
|
-
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "
|
|
58
|
+
/** As props que o preset resolve — o resto (`value`, `onChange`, `world`) é seu. */
|
|
59
|
+
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "features" | "extensions">;
|
|
67
60
|
/**
|
|
68
61
|
* As props de um campo que já nasce certo.
|
|
69
62
|
*
|
|
@@ -75,7 +68,7 @@ type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmente
|
|
|
75
68
|
* {...expressionFieldProps()}
|
|
76
69
|
* value={v}
|
|
77
70
|
* onChange={setV}
|
|
78
|
-
*
|
|
71
|
+
* world={world}
|
|
79
72
|
* />
|
|
80
73
|
* ```
|
|
81
74
|
*
|
package/dist/full.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Extension } from '@codemirror/state';
|
|
2
|
-
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-
|
|
2
|
+
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-Dsh6-SIB.js';
|
|
3
3
|
export { searchEditing } from '@tslite/codemirror/search';
|
|
4
|
-
export { format, formatExpression } from '@tslite/format';
|
|
5
4
|
export { tsliteTokenStyles } from '@tslite/editor';
|
|
6
5
|
import 'react';
|
|
7
6
|
import '@codemirror/view';
|
|
@@ -32,12 +31,6 @@ interface PresetOptions {
|
|
|
32
31
|
/**
|
|
33
32
|
* O que o código É. Padrão: `"expression"`.
|
|
34
33
|
*
|
|
35
|
-
* Decide também qual formatador entra: um programa é reimpresso com `;` e
|
|
36
|
-
* quebra de statement; uma expressão, não. Injetar o de expressão num programa
|
|
37
|
-
* faz o `parseExpression` lançar, e o serviço então declara que não sabe
|
|
38
|
-
* formatar — em silêncio. Foi um defeito real, e é por isso que o preset
|
|
39
|
-
* escolhe por você.
|
|
40
|
-
*
|
|
41
34
|
* **`"template"`** liga o controle de fluxo (`{% if %}` / `{% for %}` /
|
|
42
35
|
* `{# #}`). Ele não é o padrão porque um `{%` literal no texto deixaria de ser
|
|
43
36
|
* texto — e num campo que hoje aceita qualquer string isso seria mudança de
|
|
@@ -62,8 +55,8 @@ interface PresetOptions {
|
|
|
62
55
|
/** Extensões suas, acrescentadas às do preset. */
|
|
63
56
|
readonly extensions?: readonly Extension[];
|
|
64
57
|
}
|
|
65
|
-
/** As props que o preset resolve — o resto (`value`, `onChange`, `
|
|
66
|
-
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "
|
|
58
|
+
/** As props que o preset resolve — o resto (`value`, `onChange`, `world`) é seu. */
|
|
59
|
+
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "features" | "extensions">;
|
|
67
60
|
/**
|
|
68
61
|
* As props de um campo que já nasce certo.
|
|
69
62
|
*
|
|
@@ -75,7 +68,7 @@ type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmente
|
|
|
75
68
|
* {...expressionFieldProps()}
|
|
76
69
|
* value={v}
|
|
77
70
|
* onChange={setV}
|
|
78
|
-
*
|
|
71
|
+
* world={world}
|
|
79
72
|
* />
|
|
80
73
|
* ```
|
|
81
74
|
*
|
package/dist/full.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {searchEditing}from'@tslite/codemirror/search';export{searchEditing}from'@tslite/codemirror/search';import {
|
|
1
|
+
import {searchEditing}from'@tslite/codemirror/search';export{searchEditing}from'@tslite/codemirror/search';import {tsliteTokenStyles}from'@tslite/editor';export{tsliteTokenStyles}from'@tslite/editor';function y(r={}){let{dark:s=true,layout:e="inline",mode:o="expression",segmenter:n="mustache",gutters:i=e==="block",search:a=e==="block",extensions:t=[]}=r;return {layout:e,mode:o,...o==="template"?{}:{segmenter:n},gutters:i,features:{chrome:{dark:s},theme:tsliteTokenStyles},extensions:a?[searchEditing(),...t]:[...t]}}export{y as expressionFieldProps};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var n=require('react'),state=require('@codemirror/state'),view=require('@codemirror/view'),commands=require('@codemirror/commands'),autocomplete=require('@codemirror/autocomplete'),codemirror=require('@tslite/codemirror'),editor=require('@tslite/editor'),languageService=require('@tslite/language-service'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var n__namespace=/*#__PURE__*/_interopNamespace(n);var
|
|
1
|
+
'use strict';var n=require('react'),state=require('@codemirror/state'),view=require('@codemirror/view'),commands=require('@codemirror/commands'),autocomplete=require('@codemirror/autocomplete'),codemirror=require('@tslite/codemirror'),editor=require('@tslite/editor'),languageService=require('@tslite/language-service'),jsxRuntime=require('react/jsx-runtime');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var n__namespace=/*#__PURE__*/_interopNamespace(n);var xe={mustache:languageService.mustache,whole:languageService.whole},ye=t=>typeof t=="function"?t:xe[t];function N(t){let{world:o,service:s,segmenter:a="mustache",mode:m="expression",type:i,optional:d,profile:u,guards:c}=t,f=n__namespace.useMemo(()=>{if(s||!o)return null;let y={world:o,...i!==void 0?{type:i}:{},...d?{optional:d}:{}},R={...u?{profile:u}:{},...c?{guards:c}:{}};return m==="template"?editor.createHostService({...y,...R,mode:m}):editor.createHostService({...y,...R,segmenter:ye(a),mode:m})},[s,o,a,m,i,d,u,c]);return n__namespace.useEffect(()=>f?()=>f.dispose():void 0,[f]),s??f}var Pe=view.EditorView.theme({".cm-scroller":{overflowX:"auto",overflowY:"hidden"},".cm-content":{padding:"6px 8px"},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),ne=6,Me=view.EditorView.theme({".cm-scroller":{overflowY:"auto"},".cm-content":{padding:`${ne}px 8px`},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),Ae=(t,o)=>`${o*t.defaultLineHeight+2*ne}px`,De=view.EditorView.theme({"&":{height:"100%"},".cm-scroller":{overflowY:"auto"},".cm-content":{padding:"8px"},"&.cm-focused":{outline:"none"}}),Ie=t=>t.replace(/\r?\n/g," "),S=(t,o)=>o==="inline"?Ie(t):t,Ve=(t,o)=>{if(t===false)return [];let s=o==="block"?{}:{tab:false,indentOnInput:false};return codemirror.codeEditing(typeof t=="object"?{...s,...t}:s)},_e=t=>t?codemirror.gutters(typeof t=="object"?t:{}):[];function B(t){let{value:o,onChange:s,onCommit:a,onFinish:m,layout:i="inline",maxLines:d,wrap:u=i!=="inline",editing:c,gutters:f,readOnly:y=false,placeholder:R,features:W,tooltipParent:A,onTokenAction:$,isTokenActionable:z,definition:D,extensions:le}=t,F=N(t),I=n__namespace.useRef(null),v=n__namespace.useRef(null),[X,q]=n__namespace.useState(null),[de,pe]=n__namespace.useState(false),h=n__namespace.useRef({value:o,layout:i,onChange:s,onCommit:a,onFinish:m,onTokenAction:$,isTokenActionable:z});h.current={value:o,layout:i,onChange:s,onCommit:a,onFinish:m,onTokenAction:$,isTokenActionable:z};let O=n__namespace.useCallback(e=>{let{value:r,layout:l}=h.current;return e.state.doc.toString()!==S(r,l)},[]),V=n__namespace.useCallback((e,r)=>{let l=O(e);l&&h.current.onCommit?.(e.state.doc.toString()),h.current.onFinish?.({via:r,dirty:l});},[O]),_=n__namespace.useCallback(e=>{let{onFinish:r,value:l,layout:p}=h.current;if(!r||autocomplete.completionStatus(e.state)==="active")return false;let L=O(e);if(L){let T=S(l,p);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:T},selection:{anchor:T.length},annotations:codemirror.externalChange.of(true)});}return r({via:"escape",dirty:L}),true},[O]),g=n__namespace.useRef({service:new state.Compartment,layout:new state.Compartment,editable:new state.Compartment,actions:new state.Compartment}).current,U=n__namespace.useCallback(e=>e?codemirror.languageService(e,{theme:editor.tsliteTokenStyles,...A!==null?{tooltipParent:A??(typeof document<"u"?document.body:void 0)}:{},...W}):[],[W,A]),J=n__namespace.useCallback(e=>autocomplete.completionStatus(e.state)==="active"?autocomplete.acceptCompletion(e)||true:(V(e,"enter"),true),[V]),Y=n__namespace.useCallback((e,r,l,p)=>[e==="block"?[...r?[view.EditorView.lineWrapping]:[],De]:e==="grow"?[...r?[view.EditorView.lineWrapping]:[],Me,state.Prec.highest(view.keymap.of([{key:"Enter",run:J},{key:"Shift-Enter",run:commands.insertNewlineAndIndent},{key:"Escape",run:_}]))]:[codemirror.singleLine,Pe,state.Prec.highest(view.keymap.of([{key:"Escape",run:_}]))],Ve(l,e),_e(p)],[J,_]),G=n__namespace.useCallback(()=>{let e=[];return h.current.onTokenAction&&e.push(codemirror.tokenAction({actionable:r=>h.current.isTokenActionable?.(r)??true,onAction:r=>h.current.onTokenAction?.(r)})),D&&F?.definitionAt&&e.push(codemirror.gotoDefinition(D)),e},[D,F]);n__namespace.useEffect(()=>{if(!I.current)return;let e=new view.EditorView({parent:I.current,state:state.EditorState.create({doc:S(o,i),extensions:[commands.history(),g.service.of(U(F)),g.layout.of(Y(i,u,c,f)),g.editable.of(view.EditorView.editable.of(!y)),g.actions.of(G()),...R?[view.placeholder(R)]:[],view.keymap.of([...commands.historyKeymap,...commands.defaultKeymap]),view.EditorView.updateListener.of(r=>{if(r.focusChanged&&pe(r.view.hasFocus),!r.docChanged)return;r.transactions.some(p=>p.annotation(codemirror.externalChange))||h.current.onChange?.(r.state.doc.toString());}),view.EditorView.contentAttributes.of({"aria-label":R??"expression"}),view.EditorView.domEventHandlers({blur:(r,l)=>{let p=r.relatedTarget;return p instanceof Element&&(l.dom.contains(p)||p.closest(".cm-tooltip"))||V(l,"blur"),false}}),...le??[]]})});return v.current=e,q(e),()=>{e.destroy(),v.current=null,q(null);}},[]),n__namespace.useEffect(()=>{v.current?.dispatch({effects:g.service.reconfigure(U(F))});},[F,U,g]),n__namespace.useEffect(()=>{v.current?.dispatch({effects:g.layout.reconfigure(Y(i,u,c,f))});},[i,u,c,f,Y,g]),n__namespace.useEffect(()=>{v.current?.dispatch({effects:g.editable.reconfigure(view.EditorView.editable.of(!y))});},[y,g]),n__namespace.useEffect(()=>{let e=v.current;e&&(e.scrollDOM.style.maxHeight=i==="grow"&&d!==void 0&&d>0?Ae(e,d):"");},[i,d,X]),n__namespace.useEffect(()=>{v.current?.dispatch({effects:g.actions.reconfigure(G())});},[G,g]);let Q=n__namespace.useRef({value:o,layout:i});n__namespace.useEffect(()=>{let e=v.current;if(!e)return;let r=Q.current;Q.current={value:o,layout:i};let l=e.state.doc.toString(),p=o!==r.value||l===S(o,r.layout)?S(o,i):S(l,i);if(p===l)return;let{anchor:L,head:T}=e.state.selection.main,Z=fe=>Math.min(fe,p.length);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:p},selection:{anchor:Z(L),head:Z(T)},annotations:codemirror.externalChange.of(true)});},[o,i]);let ue=n__namespace.useCallback(()=>v.current?.focus(),[]);return {ref:I,view:X,focused:de,service:F,focus:ue}}var w=class extends Error{constructor(o,s){super(s),this.name="ExpressionFieldError",this.code=o;}};var re=n__namespace.createContext(null);function ie(){let t=n__namespace.useContext(re);if(!t)throw new w("outside-root","useFieldContext must be used inside <ExpressionField.Root>");return t}var Ue=["value","onChange","onCommit","onFinish","layout","maxLines","wrap","editing","gutters","readOnly","placeholder","features","tooltipParent","onTokenAction","isTokenActionable","definition","extensions","world","service","segmenter","mode","type","optional","profile","guards"];var se=n__namespace.forwardRef(function(o,s){let{children:a,...m}=o,i={},d={};for(let[c,f]of Object.entries(m))(Ue.includes(c)?i:d)[c]=f;let u=B(i);return jsxRuntime.jsx(re.Provider,{value:u,children:jsxRuntime.jsx("div",{ref:s,...d,children:typeof a=="function"?a(u):a})})}),ae=n__namespace.forwardRef(function(o,s){let a=ie();return jsxRuntime.jsx("div",{ref:a.ref,...o})}),ce=n__namespace.forwardRef(function({children:o,...s},a){return jsxRuntime.jsx("button",{ref:a,type:"button",...s,children:o})}),C={Root:se,Editor:ae,ExpandTrigger:ce};var E={fg:"var(--foreground, #cccccc)",mutedFg:"var(--muted-foreground, #8b8b8b)",border:"var(--border, #2b2b2b)",ring:"var(--ring, #0078d4)",input:"var(--input, transparent)",destructive:"var(--destructive, #f14c4c)",font:"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)"},Ye=["--foreground","--muted-foreground","--border","--ring","--input","--destructive","--font-mono","--muted","--popover","--popover-foreground","--primary","--primary-foreground","--secondary","--accent"];var Ge=jsxRuntime.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:jsxRuntime.jsx("path",{d:"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"})});function Ne({invalid:t,className:o,style:s,onExpand:a,expandIcon:m,multiline:i,layout:d,...u}){let c=d??(i?"block":"inline");return jsxRuntime.jsx(C.Root,{...u,layout:c,className:o,children:f=>jsxRuntime.jsxs("div",{style:{position:"relative",border:`1px solid ${t?E.destructive:f.focused?E.ring:E.border}`,borderRadius:"6px",backgroundColor:E.input,color:E.fg,fontFamily:E.font,fontSize:"13px",overflow:"hidden",...c==="block"?{height:"100%",display:"flex",flexDirection:"column"}:{},...s},children:[jsxRuntime.jsx(C.Editor,{style:c==="block"?{flex:1,minHeight:0}:c==="grow"?{paddingRight:a?"28px":void 0}:{paddingRight:a?"24px":void 0}}),a&&jsxRuntime.jsx(C.ExpandTrigger,{onClick:a,"aria-label":"Expandir",title:"Expandir",onMouseEnter:y=>y.currentTarget.style.opacity="1",onMouseLeave:y=>y.currentTarget.style.opacity="0.55",style:{position:"absolute",top:c==="inline"?"50%":"6px",right:"4px",transform:c==="inline"?"translateY(-50%)":void 0,display:"flex",alignItems:"center",justifyContent:"center",width:"20px",height:"20px",padding:0,lineHeight:0,border:"none",borderRadius:"4px",background:E.input,color:E.mutedFg,cursor:"pointer",opacity:.55},children:m??Ge})]})})}var je="1.5.0";exports.CSS_VARS=Ye;exports.ExpressionField=C;exports.ExpressionFieldEditor=ae;exports.ExpressionFieldError=w;exports.ExpressionFieldExpandTrigger=ce;exports.ExpressionFieldRoot=se;exports.ExpressionInput=Ne;exports.V=E;exports.useExpressionField=B;exports.useFieldContext=ie;exports.useLanguageService=N;exports.version=je;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-
|
|
3
|
-
export { F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField,
|
|
2
|
+
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-Dsh6-SIB.cjs';
|
|
3
|
+
export { a as FieldFinish, F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField, b as useLanguageService } from './useExpressionField-Dsh6-SIB.cjs';
|
|
4
4
|
export { TokenActionTarget } from '@tslite/codemirror';
|
|
5
5
|
import '@codemirror/state';
|
|
6
6
|
import '@codemirror/view';
|
|
@@ -31,9 +31,9 @@ interface ExpressionInputProps extends UseExpressionFieldOptions {
|
|
|
31
31
|
* O campo de expressão pronto para uso.
|
|
32
32
|
*
|
|
33
33
|
* ```tsx
|
|
34
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
35
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
36
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
34
|
+
* <ExpressionInput value={v} onChange={setV} world={world} /> // "Olá {{ user.name }}"
|
|
35
|
+
* <ExpressionInput value={v} onChange={setV} world={world} segmenter="whole" /> // "foo.bar >= 32"
|
|
36
|
+
* <ExpressionInput value={v} onChange={setV} world={world} layout="block" /> // o modal expandido
|
|
37
37
|
* ```
|
|
38
38
|
*/
|
|
39
39
|
declare function ExpressionInput({ invalid, className, style, onExpand, expandIcon, multiline, layout, ...options }: ExpressionInputProps): React.JSX.Element;
|
|
@@ -79,6 +79,16 @@ declare const ExpressionField: {
|
|
|
79
79
|
ExpandTrigger: React.ForwardRefExoticComponent<ExpandTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
/** O motivo de uma recusa. */
|
|
83
|
+
type ExpressionFieldErrorCode =
|
|
84
|
+
/** O `useFieldContext` foi chamado fora de uma `<ExpressionField.Root>`. */
|
|
85
|
+
"outside-root";
|
|
86
|
+
/** O uso errado das peças do campo. É erro de quem monta a tela, e não do autor. */
|
|
87
|
+
declare class ExpressionFieldError extends Error {
|
|
88
|
+
readonly code: ExpressionFieldErrorCode;
|
|
89
|
+
constructor(code: ExpressionFieldErrorCode, message: string);
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
/** As cores de chrome. Exportadas para o consumidor reusar no que ele desenhar. */
|
|
83
93
|
declare const V: {
|
|
84
94
|
readonly fg: "var(--foreground, #cccccc)";
|
|
@@ -93,6 +103,6 @@ declare const V: {
|
|
|
93
103
|
declare const CSS_VARS: readonly ["--foreground", "--muted-foreground", "--border", "--ring", "--input", "--destructive", "--font-mono", "--muted", "--popover", "--popover-foreground", "--primary", "--primary-foreground", "--secondary", "--accent"];
|
|
94
104
|
|
|
95
105
|
/** A versão deste package, a do módulo de fato carregado. */
|
|
96
|
-
declare const version = "1.
|
|
106
|
+
declare const version = "1.5.0";
|
|
97
107
|
|
|
98
|
-
export { CSS_VARS, ExpressionField, Editor as ExpressionFieldEditor, type EditorProps as ExpressionFieldEditorProps, ExpandTrigger as ExpressionFieldExpandTrigger, type ExpandTriggerProps as ExpressionFieldExpandTriggerProps, ExpressionFieldHandle, Root as ExpressionFieldRoot, type RootProps as ExpressionFieldRootProps, ExpressionInput, type ExpressionInputProps, UseExpressionFieldOptions, V, useFieldContext, version };
|
|
108
|
+
export { CSS_VARS, ExpressionField, Editor as ExpressionFieldEditor, type EditorProps as ExpressionFieldEditorProps, ExpressionFieldError, type ExpressionFieldErrorCode, ExpandTrigger as ExpressionFieldExpandTrigger, type ExpandTriggerProps as ExpressionFieldExpandTriggerProps, ExpressionFieldHandle, Root as ExpressionFieldRoot, type RootProps as ExpressionFieldRootProps, ExpressionInput, type ExpressionInputProps, UseExpressionFieldOptions, V, useFieldContext, version };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-
|
|
3
|
-
export { F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField,
|
|
2
|
+
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-Dsh6-SIB.js';
|
|
3
|
+
export { a as FieldFinish, F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField, b as useLanguageService } from './useExpressionField-Dsh6-SIB.js';
|
|
4
4
|
export { TokenActionTarget } from '@tslite/codemirror';
|
|
5
5
|
import '@codemirror/state';
|
|
6
6
|
import '@codemirror/view';
|
|
@@ -31,9 +31,9 @@ interface ExpressionInputProps extends UseExpressionFieldOptions {
|
|
|
31
31
|
* O campo de expressão pronto para uso.
|
|
32
32
|
*
|
|
33
33
|
* ```tsx
|
|
34
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
35
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
36
|
-
* <ExpressionInput value={v} onChange={setV}
|
|
34
|
+
* <ExpressionInput value={v} onChange={setV} world={world} /> // "Olá {{ user.name }}"
|
|
35
|
+
* <ExpressionInput value={v} onChange={setV} world={world} segmenter="whole" /> // "foo.bar >= 32"
|
|
36
|
+
* <ExpressionInput value={v} onChange={setV} world={world} layout="block" /> // o modal expandido
|
|
37
37
|
* ```
|
|
38
38
|
*/
|
|
39
39
|
declare function ExpressionInput({ invalid, className, style, onExpand, expandIcon, multiline, layout, ...options }: ExpressionInputProps): React.JSX.Element;
|
|
@@ -79,6 +79,16 @@ declare const ExpressionField: {
|
|
|
79
79
|
ExpandTrigger: React.ForwardRefExoticComponent<ExpandTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
/** O motivo de uma recusa. */
|
|
83
|
+
type ExpressionFieldErrorCode =
|
|
84
|
+
/** O `useFieldContext` foi chamado fora de uma `<ExpressionField.Root>`. */
|
|
85
|
+
"outside-root";
|
|
86
|
+
/** O uso errado das peças do campo. É erro de quem monta a tela, e não do autor. */
|
|
87
|
+
declare class ExpressionFieldError extends Error {
|
|
88
|
+
readonly code: ExpressionFieldErrorCode;
|
|
89
|
+
constructor(code: ExpressionFieldErrorCode, message: string);
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
/** As cores de chrome. Exportadas para o consumidor reusar no que ele desenhar. */
|
|
83
93
|
declare const V: {
|
|
84
94
|
readonly fg: "var(--foreground, #cccccc)";
|
|
@@ -93,6 +103,6 @@ declare const V: {
|
|
|
93
103
|
declare const CSS_VARS: readonly ["--foreground", "--muted-foreground", "--border", "--ring", "--input", "--destructive", "--font-mono", "--muted", "--popover", "--popover-foreground", "--primary", "--primary-foreground", "--secondary", "--accent"];
|
|
94
104
|
|
|
95
105
|
/** A versão deste package, a do módulo de fato carregado. */
|
|
96
|
-
declare const version = "1.
|
|
106
|
+
declare const version = "1.5.0";
|
|
97
107
|
|
|
98
|
-
export { CSS_VARS, ExpressionField, Editor as ExpressionFieldEditor, type EditorProps as ExpressionFieldEditorProps, ExpandTrigger as ExpressionFieldExpandTrigger, type ExpandTriggerProps as ExpressionFieldExpandTriggerProps, ExpressionFieldHandle, Root as ExpressionFieldRoot, type RootProps as ExpressionFieldRootProps, ExpressionInput, type ExpressionInputProps, UseExpressionFieldOptions, V, useFieldContext, version };
|
|
108
|
+
export { CSS_VARS, ExpressionField, Editor as ExpressionFieldEditor, type EditorProps as ExpressionFieldEditorProps, ExpressionFieldError, type ExpressionFieldErrorCode, ExpandTrigger as ExpressionFieldExpandTrigger, type ExpandTriggerProps as ExpressionFieldExpandTriggerProps, ExpressionFieldHandle, Root as ExpressionFieldRoot, type RootProps as ExpressionFieldRootProps, ExpressionInput, type ExpressionInputProps, UseExpressionFieldOptions, V, useFieldContext, version };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as n from'react';import {Compartment,Prec,EditorState}from'@codemirror/state';import {EditorView,keymap,placeholder}from'@codemirror/view';import {insertNewlineAndIndent,history,historyKeymap,defaultKeymap}from'@codemirror/commands';import {completionStatus,acceptCompletion}from'@codemirror/autocomplete';import {languageService,singleLine,tokenAction,gotoDefinition,
|
|
1
|
+
import*as n from'react';import {Compartment,Prec,EditorState}from'@codemirror/state';import {EditorView,keymap,placeholder}from'@codemirror/view';import {insertNewlineAndIndent,history,historyKeymap,defaultKeymap}from'@codemirror/commands';import {completionStatus,acceptCompletion}from'@codemirror/autocomplete';import {externalChange,languageService,singleLine,tokenAction,gotoDefinition,codeEditing,gutters}from'@tslite/codemirror';import {tsliteTokenStyles,createHostService}from'@tslite/editor';import {whole,mustache}from'@tslite/language-service';import {jsx,jsxs}from'react/jsx-runtime';var xe={mustache:mustache,whole:whole},ye=t=>typeof t=="function"?t:xe[t];function N(t){let{world:o,service:s,segmenter:a="mustache",mode:m="expression",type:i,optional:d,profile:u,guards:c}=t,f=n.useMemo(()=>{if(s||!o)return null;let y={world:o,...i!==void 0?{type:i}:{},...d?{optional:d}:{}},R={...u?{profile:u}:{},...c?{guards:c}:{}};return m==="template"?createHostService({...y,...R,mode:m}):createHostService({...y,...R,segmenter:ye(a),mode:m})},[s,o,a,m,i,d,u,c]);return n.useEffect(()=>f?()=>f.dispose():void 0,[f]),s??f}var Pe=EditorView.theme({".cm-scroller":{overflowX:"auto",overflowY:"hidden"},".cm-content":{padding:"6px 8px"},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),ne=6,Me=EditorView.theme({".cm-scroller":{overflowY:"auto"},".cm-content":{padding:`${ne}px 8px`},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),Ae=(t,o)=>`${o*t.defaultLineHeight+2*ne}px`,De=EditorView.theme({"&":{height:"100%"},".cm-scroller":{overflowY:"auto"},".cm-content":{padding:"8px"},"&.cm-focused":{outline:"none"}}),Ie=t=>t.replace(/\r?\n/g," "),S=(t,o)=>o==="inline"?Ie(t):t,Ve=(t,o)=>{if(t===false)return [];let s=o==="block"?{}:{tab:false,indentOnInput:false};return codeEditing(typeof t=="object"?{...s,...t}:s)},_e=t=>t?gutters(typeof t=="object"?t:{}):[];function B(t){let{value:o,onChange:s,onCommit:a,onFinish:m,layout:i="inline",maxLines:d,wrap:u=i!=="inline",editing:c,gutters:f,readOnly:y=false,placeholder:R,features:W,tooltipParent:A,onTokenAction:$,isTokenActionable:z,definition:D,extensions:le}=t,F=N(t),I=n.useRef(null),v=n.useRef(null),[X,q]=n.useState(null),[de,pe]=n.useState(false),h=n.useRef({value:o,layout:i,onChange:s,onCommit:a,onFinish:m,onTokenAction:$,isTokenActionable:z});h.current={value:o,layout:i,onChange:s,onCommit:a,onFinish:m,onTokenAction:$,isTokenActionable:z};let O=n.useCallback(e=>{let{value:r,layout:l}=h.current;return e.state.doc.toString()!==S(r,l)},[]),V=n.useCallback((e,r)=>{let l=O(e);l&&h.current.onCommit?.(e.state.doc.toString()),h.current.onFinish?.({via:r,dirty:l});},[O]),_=n.useCallback(e=>{let{onFinish:r,value:l,layout:p}=h.current;if(!r||completionStatus(e.state)==="active")return false;let L=O(e);if(L){let T=S(l,p);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:T},selection:{anchor:T.length},annotations:externalChange.of(true)});}return r({via:"escape",dirty:L}),true},[O]),g=n.useRef({service:new Compartment,layout:new Compartment,editable:new Compartment,actions:new Compartment}).current,U=n.useCallback(e=>e?languageService(e,{theme:tsliteTokenStyles,...A!==null?{tooltipParent:A??(typeof document<"u"?document.body:void 0)}:{},...W}):[],[W,A]),J=n.useCallback(e=>completionStatus(e.state)==="active"?acceptCompletion(e)||true:(V(e,"enter"),true),[V]),Y=n.useCallback((e,r,l,p)=>[e==="block"?[...r?[EditorView.lineWrapping]:[],De]:e==="grow"?[...r?[EditorView.lineWrapping]:[],Me,Prec.highest(keymap.of([{key:"Enter",run:J},{key:"Shift-Enter",run:insertNewlineAndIndent},{key:"Escape",run:_}]))]:[singleLine,Pe,Prec.highest(keymap.of([{key:"Escape",run:_}]))],Ve(l,e),_e(p)],[J,_]),G=n.useCallback(()=>{let e=[];return h.current.onTokenAction&&e.push(tokenAction({actionable:r=>h.current.isTokenActionable?.(r)??true,onAction:r=>h.current.onTokenAction?.(r)})),D&&F?.definitionAt&&e.push(gotoDefinition(D)),e},[D,F]);n.useEffect(()=>{if(!I.current)return;let e=new EditorView({parent:I.current,state:EditorState.create({doc:S(o,i),extensions:[history(),g.service.of(U(F)),g.layout.of(Y(i,u,c,f)),g.editable.of(EditorView.editable.of(!y)),g.actions.of(G()),...R?[placeholder(R)]:[],keymap.of([...historyKeymap,...defaultKeymap]),EditorView.updateListener.of(r=>{if(r.focusChanged&&pe(r.view.hasFocus),!r.docChanged)return;r.transactions.some(p=>p.annotation(externalChange))||h.current.onChange?.(r.state.doc.toString());}),EditorView.contentAttributes.of({"aria-label":R??"expression"}),EditorView.domEventHandlers({blur:(r,l)=>{let p=r.relatedTarget;return p instanceof Element&&(l.dom.contains(p)||p.closest(".cm-tooltip"))||V(l,"blur"),false}}),...le??[]]})});return v.current=e,q(e),()=>{e.destroy(),v.current=null,q(null);}},[]),n.useEffect(()=>{v.current?.dispatch({effects:g.service.reconfigure(U(F))});},[F,U,g]),n.useEffect(()=>{v.current?.dispatch({effects:g.layout.reconfigure(Y(i,u,c,f))});},[i,u,c,f,Y,g]),n.useEffect(()=>{v.current?.dispatch({effects:g.editable.reconfigure(EditorView.editable.of(!y))});},[y,g]),n.useEffect(()=>{let e=v.current;e&&(e.scrollDOM.style.maxHeight=i==="grow"&&d!==void 0&&d>0?Ae(e,d):"");},[i,d,X]),n.useEffect(()=>{v.current?.dispatch({effects:g.actions.reconfigure(G())});},[G,g]);let Q=n.useRef({value:o,layout:i});n.useEffect(()=>{let e=v.current;if(!e)return;let r=Q.current;Q.current={value:o,layout:i};let l=e.state.doc.toString(),p=o!==r.value||l===S(o,r.layout)?S(o,i):S(l,i);if(p===l)return;let{anchor:L,head:T}=e.state.selection.main,Z=fe=>Math.min(fe,p.length);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:p},selection:{anchor:Z(L),head:Z(T)},annotations:externalChange.of(true)});},[o,i]);let ue=n.useCallback(()=>v.current?.focus(),[]);return {ref:I,view:X,focused:de,service:F,focus:ue}}var w=class extends Error{constructor(o,s){super(s),this.name="ExpressionFieldError",this.code=o;}};var re=n.createContext(null);function ie(){let t=n.useContext(re);if(!t)throw new w("outside-root","useFieldContext must be used inside <ExpressionField.Root>");return t}var Ue=["value","onChange","onCommit","onFinish","layout","maxLines","wrap","editing","gutters","readOnly","placeholder","features","tooltipParent","onTokenAction","isTokenActionable","definition","extensions","world","service","segmenter","mode","type","optional","profile","guards"];var se=n.forwardRef(function(o,s){let{children:a,...m}=o,i={},d={};for(let[c,f]of Object.entries(m))(Ue.includes(c)?i:d)[c]=f;let u=B(i);return jsx(re.Provider,{value:u,children:jsx("div",{ref:s,...d,children:typeof a=="function"?a(u):a})})}),ae=n.forwardRef(function(o,s){let a=ie();return jsx("div",{ref:a.ref,...o})}),ce=n.forwardRef(function({children:o,...s},a){return jsx("button",{ref:a,type:"button",...s,children:o})}),C={Root:se,Editor:ae,ExpandTrigger:ce};var E={fg:"var(--foreground, #cccccc)",mutedFg:"var(--muted-foreground, #8b8b8b)",border:"var(--border, #2b2b2b)",ring:"var(--ring, #0078d4)",input:"var(--input, transparent)",destructive:"var(--destructive, #f14c4c)",font:"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)"},Ye=["--foreground","--muted-foreground","--border","--ring","--input","--destructive","--font-mono","--muted","--popover","--popover-foreground","--primary","--primary-foreground","--secondary","--accent"];var Ge=jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:jsx("path",{d:"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"})});function Ne({invalid:t,className:o,style:s,onExpand:a,expandIcon:m,multiline:i,layout:d,...u}){let c=d??(i?"block":"inline");return jsx(C.Root,{...u,layout:c,className:o,children:f=>jsxs("div",{style:{position:"relative",border:`1px solid ${t?E.destructive:f.focused?E.ring:E.border}`,borderRadius:"6px",backgroundColor:E.input,color:E.fg,fontFamily:E.font,fontSize:"13px",overflow:"hidden",...c==="block"?{height:"100%",display:"flex",flexDirection:"column"}:{},...s},children:[jsx(C.Editor,{style:c==="block"?{flex:1,minHeight:0}:c==="grow"?{paddingRight:a?"28px":void 0}:{paddingRight:a?"24px":void 0}}),a&&jsx(C.ExpandTrigger,{onClick:a,"aria-label":"Expandir",title:"Expandir",onMouseEnter:y=>y.currentTarget.style.opacity="1",onMouseLeave:y=>y.currentTarget.style.opacity="0.55",style:{position:"absolute",top:c==="inline"?"50%":"6px",right:"4px",transform:c==="inline"?"translateY(-50%)":void 0,display:"flex",alignItems:"center",justifyContent:"center",width:"20px",height:"20px",padding:0,lineHeight:0,border:"none",borderRadius:"4px",background:E.input,color:E.mutedFg,cursor:"pointer",opacity:.55},children:m??Ge})]})})}var je="1.5.0";export{Ye as CSS_VARS,C as ExpressionField,ae as ExpressionFieldEditor,w as ExpressionFieldError,ce as ExpressionFieldExpandTrigger,se as ExpressionFieldRoot,Ne as ExpressionInput,E as V,B as useExpressionField,ie as useFieldContext,N as useLanguageService,je as version};
|
|
@@ -3,7 +3,7 @@ import { Extension } from '@codemirror/state';
|
|
|
3
3
|
import { EditorView } from '@codemirror/view';
|
|
4
4
|
import { CodeEditingOptions, GuttersOptions, LanguageServiceOptions as LanguageServiceOptions$1, TokenActionTarget, GotoDefinitionOptions } from '@tslite/codemirror';
|
|
5
5
|
import { Segmenter, LanguageService, Token } from '@tslite/language-service';
|
|
6
|
-
import { HostServiceOptions } from '@tslite/editor';
|
|
6
|
+
import { HostServiceOptions, HostServiceCodeOptions } from '@tslite/editor';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Onde, no texto, mora o código.
|
|
@@ -16,14 +16,16 @@ type SegmenterOption = "mustache" | "whole" | Segmenter;
|
|
|
16
16
|
/** O que define o cérebro do campo. */
|
|
17
17
|
interface LanguageServiceOptions {
|
|
18
18
|
/**
|
|
19
|
-
* O
|
|
19
|
+
* O mundo em que o campo se tipa (`createWorld` do `@tslite/editor`): a lib da
|
|
20
|
+
* cópia do tsc, o `.d.ts` do `std` e as declarações do host. Os campos de uma
|
|
21
|
+
* tela dividem o mesmo mundo, e cada um é um arquivo virtual dele.
|
|
20
22
|
*
|
|
21
|
-
* **
|
|
22
|
-
*
|
|
23
|
+
* **Crie-o uma vez** (fora do render, ou num `useMemo`). Um mundo novo a cada
|
|
24
|
+
* render reconstrói o serviço e reparseia a lib.
|
|
23
25
|
*/
|
|
24
|
-
readonly
|
|
26
|
+
readonly world?: HostServiceOptions["world"];
|
|
25
27
|
/**
|
|
26
|
-
* Um serviço pronto, no lugar do `
|
|
28
|
+
* Um serviço pronto, no lugar do `world`. Tem precedência — e é o caminho para
|
|
27
29
|
* trocar o cérebro por outro (outra linguagem, outra implementação).
|
|
28
30
|
*/
|
|
29
31
|
readonly service?: LanguageService;
|
|
@@ -53,19 +55,12 @@ interface LanguageServiceOptions {
|
|
|
53
55
|
*/
|
|
54
56
|
readonly mode?: "expression" | "program" | "template";
|
|
55
57
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* profile cabe num campo é decisão de produto.
|
|
58
|
+
* O tipo que o valor do campo tem de ter, como o texto de um tipo
|
|
59
|
+
* (`"boolean"`, `"Address"`): o campo acusa, enquanto se digita, o valor que
|
|
60
|
+
* não cabe nele. Vale para a expressão e para o template; um programa não tem
|
|
61
|
+
* valor. Sem ele, o campo aceita qualquer tipo.
|
|
61
62
|
*/
|
|
62
|
-
readonly
|
|
63
|
-
/** Limites estruturais (anti-DoS). */
|
|
64
|
-
readonly limits?: HostServiceOptions["limits"];
|
|
65
|
-
/** Bindings nunca lidos. Ligado por padrão (é API de editor). */
|
|
66
|
-
readonly unused?: HostServiceOptions["unused"];
|
|
67
|
-
/** O formatador (`formatExpression` do `@tslite/format`). Sem ele, não formata. */
|
|
68
|
-
readonly format?: HostServiceOptions["format"];
|
|
63
|
+
readonly type?: HostServiceOptions["type"];
|
|
69
64
|
/**
|
|
70
65
|
* O campo aceita ficar vazio: o texto vazio, ou só com espaços, é a ausência do
|
|
71
66
|
* valor, e não o erro de "falta a expressão". Padrão: `false`. As sugestões no
|
|
@@ -73,10 +68,33 @@ interface LanguageServiceOptions {
|
|
|
73
68
|
* (`createHostService({ optional })`).
|
|
74
69
|
*/
|
|
75
70
|
readonly optional?: HostServiceOptions["optional"];
|
|
71
|
+
/**
|
|
72
|
+
* O perfil de capability do campo (o `@tslite/capability`): o que o campo pode
|
|
73
|
+
* escrever. O que ele recusa sai nos diagnósticos, enquanto se digita, sobre o
|
|
74
|
+
* texto que parseia (a E32 do `@tslite/editor`), com o veredito do executor e o da
|
|
75
|
+
* camada de controle. Sem padrão: sem ele, nada se poda (R18).
|
|
76
|
+
*
|
|
77
|
+
* **Crie-o uma vez**, como o `world`: um perfil novo a cada render reconstrói o
|
|
78
|
+
* serviço. No `mode: "template"`, ele julga o que o template desaçucara (o `map`
|
|
79
|
+
* de um `{% for %}`), como o executor, e a violação pousa na diretiva (a E34 do
|
|
80
|
+
* `@tslite/editor`). Com `service`, o perfil é de quem montou o serviço.
|
|
81
|
+
*/
|
|
82
|
+
readonly profile?: HostServiceCodeOptions["profile"];
|
|
83
|
+
/**
|
|
84
|
+
* As regras a mais da camada de controle do `@tslite/behavior` (as de forma, as da
|
|
85
|
+
* aplicação), nos diagnósticos como as do perfil. Valem as mesmas regras do
|
|
86
|
+
* `profile`: crie-as uma vez.
|
|
87
|
+
*/
|
|
88
|
+
readonly guards?: HostServiceCodeOptions["guards"];
|
|
76
89
|
}
|
|
77
90
|
/**
|
|
78
|
-
* O `LanguageService` do campo. `null` quando não há `
|
|
91
|
+
* O `LanguageService` do campo. `null` quando não há `world` nem `service` — o
|
|
79
92
|
* editor continua editando texto, só sem inteligência.
|
|
93
|
+
*
|
|
94
|
+
* O serviço que o hook monta põe os arquivos virtuais do campo no mundo; quando
|
|
95
|
+
* ele é trocado (uma opção mudou) ou o campo desmonta, o hook os tira (o
|
|
96
|
+
* `dispose`, E28 do `@tslite/editor`). O `service` passado é de quem o montou, e
|
|
97
|
+
* o hook não o solta.
|
|
80
98
|
*/
|
|
81
99
|
declare function useLanguageService(options: LanguageServiceOptions): LanguageService | null;
|
|
82
100
|
|
|
@@ -113,6 +131,20 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
113
131
|
* não é o autor terminando, e não commita.
|
|
114
132
|
*/
|
|
115
133
|
readonly onCommit?: (text: string) => void;
|
|
134
|
+
/**
|
|
135
|
+
* O GESTO com que o autor terminou: o `Enter` que termina (layout `"grow"`), o
|
|
136
|
+
* `Escape` que cancela (layouts `"inline"` e `"grow"`) ou o foco que sai. Dispara
|
|
137
|
+
* também quando nada mudou, com `dirty` dizendo se havia rascunho diferente do
|
|
138
|
+
* `value` naquele instante (R19).
|
|
139
|
+
*
|
|
140
|
+
* No `Enter` e no blur, ele vem depois do `onCommit` (quando há o que commitar):
|
|
141
|
+
* quem recusa o texto no `onCommit` já recusou quando o gesto chega. O `Escape`
|
|
142
|
+
* volta o rascunho ao `value`, sem `onChange` nem `onCommit`, e avisa. A tecla
|
|
143
|
+
* que a lista de sugestões consome (o `Enter` que aceita, o `Escape` que fecha)
|
|
144
|
+
* não é o autor terminando, e não dispara. Sem esta função, o `Escape` não é do
|
|
145
|
+
* campo.
|
|
146
|
+
*/
|
|
147
|
+
readonly onFinish?: (finish: FieldFinish) => void;
|
|
116
148
|
/** Como o campo se apresenta. Padrão: `"inline"`. */
|
|
117
149
|
readonly layout?: FieldLayout;
|
|
118
150
|
/**
|
|
@@ -193,6 +225,13 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
193
225
|
/** Extensões extras do CodeMirror — a escotilha de fuga. */
|
|
194
226
|
readonly extensions?: readonly Extension[];
|
|
195
227
|
}
|
|
228
|
+
/** Como o autor terminou a edição do campo (R19). */
|
|
229
|
+
interface FieldFinish {
|
|
230
|
+
/** O gesto: o `Enter` que termina, o `Escape` que cancela, ou o foco que sai. */
|
|
231
|
+
readonly via: "enter" | "escape" | "blur";
|
|
232
|
+
/** Havia rascunho diferente do `value` quando o autor terminou. */
|
|
233
|
+
readonly dirty: boolean;
|
|
234
|
+
}
|
|
196
235
|
/** O que o hook devolve. */
|
|
197
236
|
interface ExpressionFieldHandle {
|
|
198
237
|
/** Ponha num elemento vazio: é onde o editor monta. */
|
|
@@ -208,4 +247,4 @@ interface ExpressionFieldHandle {
|
|
|
208
247
|
}
|
|
209
248
|
declare function useExpressionField(options: UseExpressionFieldOptions): ExpressionFieldHandle;
|
|
210
249
|
|
|
211
|
-
export { type ExpressionFieldHandle as E, type FieldLayout as F, type LanguageServiceOptions as L, type SegmenterOption as S, type UseExpressionFieldOptions as U,
|
|
250
|
+
export { type ExpressionFieldHandle as E, type FieldLayout as F, type LanguageServiceOptions as L, type SegmenterOption as S, type UseExpressionFieldOptions as U, type FieldFinish as a, useLanguageService as b, useExpressionField as u };
|
|
@@ -3,7 +3,7 @@ import { Extension } from '@codemirror/state';
|
|
|
3
3
|
import { EditorView } from '@codemirror/view';
|
|
4
4
|
import { CodeEditingOptions, GuttersOptions, LanguageServiceOptions as LanguageServiceOptions$1, TokenActionTarget, GotoDefinitionOptions } from '@tslite/codemirror';
|
|
5
5
|
import { Segmenter, LanguageService, Token } from '@tslite/language-service';
|
|
6
|
-
import { HostServiceOptions } from '@tslite/editor';
|
|
6
|
+
import { HostServiceOptions, HostServiceCodeOptions } from '@tslite/editor';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Onde, no texto, mora o código.
|
|
@@ -16,14 +16,16 @@ type SegmenterOption = "mustache" | "whole" | Segmenter;
|
|
|
16
16
|
/** O que define o cérebro do campo. */
|
|
17
17
|
interface LanguageServiceOptions {
|
|
18
18
|
/**
|
|
19
|
-
* O
|
|
19
|
+
* O mundo em que o campo se tipa (`createWorld` do `@tslite/editor`): a lib da
|
|
20
|
+
* cópia do tsc, o `.d.ts` do `std` e as declarações do host. Os campos de uma
|
|
21
|
+
* tela dividem o mesmo mundo, e cada um é um arquivo virtual dele.
|
|
20
22
|
*
|
|
21
|
-
* **
|
|
22
|
-
*
|
|
23
|
+
* **Crie-o uma vez** (fora do render, ou num `useMemo`). Um mundo novo a cada
|
|
24
|
+
* render reconstrói o serviço e reparseia a lib.
|
|
23
25
|
*/
|
|
24
|
-
readonly
|
|
26
|
+
readonly world?: HostServiceOptions["world"];
|
|
25
27
|
/**
|
|
26
|
-
* Um serviço pronto, no lugar do `
|
|
28
|
+
* Um serviço pronto, no lugar do `world`. Tem precedência — e é o caminho para
|
|
27
29
|
* trocar o cérebro por outro (outra linguagem, outra implementação).
|
|
28
30
|
*/
|
|
29
31
|
readonly service?: LanguageService;
|
|
@@ -53,19 +55,12 @@ interface LanguageServiceOptions {
|
|
|
53
55
|
*/
|
|
54
56
|
readonly mode?: "expression" | "program" | "template";
|
|
55
57
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* profile cabe num campo é decisão de produto.
|
|
58
|
+
* O tipo que o valor do campo tem de ter, como o texto de um tipo
|
|
59
|
+
* (`"boolean"`, `"Address"`): o campo acusa, enquanto se digita, o valor que
|
|
60
|
+
* não cabe nele. Vale para a expressão e para o template; um programa não tem
|
|
61
|
+
* valor. Sem ele, o campo aceita qualquer tipo.
|
|
61
62
|
*/
|
|
62
|
-
readonly
|
|
63
|
-
/** Limites estruturais (anti-DoS). */
|
|
64
|
-
readonly limits?: HostServiceOptions["limits"];
|
|
65
|
-
/** Bindings nunca lidos. Ligado por padrão (é API de editor). */
|
|
66
|
-
readonly unused?: HostServiceOptions["unused"];
|
|
67
|
-
/** O formatador (`formatExpression` do `@tslite/format`). Sem ele, não formata. */
|
|
68
|
-
readonly format?: HostServiceOptions["format"];
|
|
63
|
+
readonly type?: HostServiceOptions["type"];
|
|
69
64
|
/**
|
|
70
65
|
* O campo aceita ficar vazio: o texto vazio, ou só com espaços, é a ausência do
|
|
71
66
|
* valor, e não o erro de "falta a expressão". Padrão: `false`. As sugestões no
|
|
@@ -73,10 +68,33 @@ interface LanguageServiceOptions {
|
|
|
73
68
|
* (`createHostService({ optional })`).
|
|
74
69
|
*/
|
|
75
70
|
readonly optional?: HostServiceOptions["optional"];
|
|
71
|
+
/**
|
|
72
|
+
* O perfil de capability do campo (o `@tslite/capability`): o que o campo pode
|
|
73
|
+
* escrever. O que ele recusa sai nos diagnósticos, enquanto se digita, sobre o
|
|
74
|
+
* texto que parseia (a E32 do `@tslite/editor`), com o veredito do executor e o da
|
|
75
|
+
* camada de controle. Sem padrão: sem ele, nada se poda (R18).
|
|
76
|
+
*
|
|
77
|
+
* **Crie-o uma vez**, como o `world`: um perfil novo a cada render reconstrói o
|
|
78
|
+
* serviço. No `mode: "template"`, ele julga o que o template desaçucara (o `map`
|
|
79
|
+
* de um `{% for %}`), como o executor, e a violação pousa na diretiva (a E34 do
|
|
80
|
+
* `@tslite/editor`). Com `service`, o perfil é de quem montou o serviço.
|
|
81
|
+
*/
|
|
82
|
+
readonly profile?: HostServiceCodeOptions["profile"];
|
|
83
|
+
/**
|
|
84
|
+
* As regras a mais da camada de controle do `@tslite/behavior` (as de forma, as da
|
|
85
|
+
* aplicação), nos diagnósticos como as do perfil. Valem as mesmas regras do
|
|
86
|
+
* `profile`: crie-as uma vez.
|
|
87
|
+
*/
|
|
88
|
+
readonly guards?: HostServiceCodeOptions["guards"];
|
|
76
89
|
}
|
|
77
90
|
/**
|
|
78
|
-
* O `LanguageService` do campo. `null` quando não há `
|
|
91
|
+
* O `LanguageService` do campo. `null` quando não há `world` nem `service` — o
|
|
79
92
|
* editor continua editando texto, só sem inteligência.
|
|
93
|
+
*
|
|
94
|
+
* O serviço que o hook monta põe os arquivos virtuais do campo no mundo; quando
|
|
95
|
+
* ele é trocado (uma opção mudou) ou o campo desmonta, o hook os tira (o
|
|
96
|
+
* `dispose`, E28 do `@tslite/editor`). O `service` passado é de quem o montou, e
|
|
97
|
+
* o hook não o solta.
|
|
80
98
|
*/
|
|
81
99
|
declare function useLanguageService(options: LanguageServiceOptions): LanguageService | null;
|
|
82
100
|
|
|
@@ -113,6 +131,20 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
113
131
|
* não é o autor terminando, e não commita.
|
|
114
132
|
*/
|
|
115
133
|
readonly onCommit?: (text: string) => void;
|
|
134
|
+
/**
|
|
135
|
+
* O GESTO com que o autor terminou: o `Enter` que termina (layout `"grow"`), o
|
|
136
|
+
* `Escape` que cancela (layouts `"inline"` e `"grow"`) ou o foco que sai. Dispara
|
|
137
|
+
* também quando nada mudou, com `dirty` dizendo se havia rascunho diferente do
|
|
138
|
+
* `value` naquele instante (R19).
|
|
139
|
+
*
|
|
140
|
+
* No `Enter` e no blur, ele vem depois do `onCommit` (quando há o que commitar):
|
|
141
|
+
* quem recusa o texto no `onCommit` já recusou quando o gesto chega. O `Escape`
|
|
142
|
+
* volta o rascunho ao `value`, sem `onChange` nem `onCommit`, e avisa. A tecla
|
|
143
|
+
* que a lista de sugestões consome (o `Enter` que aceita, o `Escape` que fecha)
|
|
144
|
+
* não é o autor terminando, e não dispara. Sem esta função, o `Escape` não é do
|
|
145
|
+
* campo.
|
|
146
|
+
*/
|
|
147
|
+
readonly onFinish?: (finish: FieldFinish) => void;
|
|
116
148
|
/** Como o campo se apresenta. Padrão: `"inline"`. */
|
|
117
149
|
readonly layout?: FieldLayout;
|
|
118
150
|
/**
|
|
@@ -193,6 +225,13 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
193
225
|
/** Extensões extras do CodeMirror — a escotilha de fuga. */
|
|
194
226
|
readonly extensions?: readonly Extension[];
|
|
195
227
|
}
|
|
228
|
+
/** Como o autor terminou a edição do campo (R19). */
|
|
229
|
+
interface FieldFinish {
|
|
230
|
+
/** O gesto: o `Enter` que termina, o `Escape` que cancela, ou o foco que sai. */
|
|
231
|
+
readonly via: "enter" | "escape" | "blur";
|
|
232
|
+
/** Havia rascunho diferente do `value` quando o autor terminou. */
|
|
233
|
+
readonly dirty: boolean;
|
|
234
|
+
}
|
|
196
235
|
/** O que o hook devolve. */
|
|
197
236
|
interface ExpressionFieldHandle {
|
|
198
237
|
/** Ponha num elemento vazio: é onde o editor monta. */
|
|
@@ -208,4 +247,4 @@ interface ExpressionFieldHandle {
|
|
|
208
247
|
}
|
|
209
248
|
declare function useExpressionField(options: UseExpressionFieldOptions): ExpressionFieldHandle;
|
|
210
249
|
|
|
211
|
-
export { type ExpressionFieldHandle as E, type FieldLayout as F, type LanguageServiceOptions as L, type SegmenterOption as S, type UseExpressionFieldOptions as U,
|
|
250
|
+
export { type ExpressionFieldHandle as E, type FieldLayout as F, type LanguageServiceOptions as L, type SegmenterOption as S, type UseExpressionFieldOptions as U, type FieldFinish as a, useLanguageService as b, useExpressionField as u };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tslite/react",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "React bindings for TSLite — a headless expression field (CodeMirror 6) with type-aware highlighting, completion, diagnostics and quick-fixes, driven by the TSLite
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "React bindings for TSLite — a headless expression field (CodeMirror 6) with type-aware highlighting, completion, diagnostics and quick-fixes, driven by the TypeScript language service ported to TSLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -48,8 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@tslite/codemirror": "^1.3.0",
|
|
51
|
-
"@tslite/editor": "^1.
|
|
52
|
-
"@tslite/format": "^1.4.0",
|
|
51
|
+
"@tslite/editor": "^1.7.0",
|
|
53
52
|
"@tslite/language-service": "^1.2.0"
|
|
54
53
|
},
|
|
55
54
|
"peerDependencies": {
|
|
@@ -61,8 +60,7 @@
|
|
|
61
60
|
"@codemirror/state": "^6.0.0",
|
|
62
61
|
"@codemirror/view": "^6.37.0",
|
|
63
62
|
"react": ">=18",
|
|
64
|
-
"react-dom": ">=18"
|
|
65
|
-
"@tslite/checker": "^1.8.0"
|
|
63
|
+
"react-dom": ">=18"
|
|
66
64
|
},
|
|
67
65
|
"devDependencies": {
|
|
68
66
|
"@codemirror/autocomplete": "^6.20.3",
|
|
@@ -77,7 +75,8 @@
|
|
|
77
75
|
"@types/react-dom": "^18.3.1",
|
|
78
76
|
"react": "^18.3.1",
|
|
79
77
|
"react-dom": "^18.3.1",
|
|
80
|
-
"@tslite/checker": "1.
|
|
78
|
+
"@tslite/checker": "1.13.0",
|
|
79
|
+
"@tslite/std": "1.4.0"
|
|
81
80
|
},
|
|
82
81
|
"peerDependenciesMeta": {
|
|
83
82
|
"@codemirror/search": {
|