@tslite/react 0.2.12 → 0.3.1
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 +17 -4
- package/dist/full.d.ts +17 -4
- package/dist/full.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{useExpressionField-CmiOEqIK.d.cts → useExpressionField-RJzhO-r7.d.cts} +36 -7
- package/dist/{useExpressionField-CmiOEqIK.d.ts → useExpressionField-RJzhO-r7.d.ts} +36 -7
- package/package.json +6 -6
package/dist/full.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var search=require('@tslite/codemirror/search'),format=require('@tslite/format'),editor=require('@tslite/editor');function
|
|
1
|
+
'use strict';var search=require('@tslite/codemirror/search'),format=require('@tslite/format'),editor=require('@tslite/editor');function u(t={}){let{dark:s=true,layout:e="inline",mode:o="expression",segmenter:n="mustache",gutters:i=e==="block",search:a=e==="block",extensions:r=[]}=t;return {layout:e,mode:o,...o==="template"?{}:{segmenter:n},gutters:i,format:o==="program"?format.format:format.formatExpression,features:{chrome:{dark:s},theme:editor.tsliteTokenStyles},extensions:a?[search.searchEditing(),...r]:[...r]}}Object.defineProperty(exports,"searchEditing",{enumerable:true,get:function(){return search.searchEditing}});Object.defineProperty(exports,"format",{enumerable:true,get:function(){return format.format}});Object.defineProperty(exports,"formatExpression",{enumerable:true,get:function(){return format.formatExpression}});Object.defineProperty(exports,"tsliteTokenStyles",{enumerable:true,get:function(){return editor.tsliteTokenStyles}});exports.expressionFieldProps=u;
|
package/dist/full.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Extension } from '@codemirror/state';
|
|
2
|
-
import { U as UseExpressionFieldOptions } from './useExpressionField-
|
|
2
|
+
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-RJzhO-r7.cjs';
|
|
3
3
|
export { searchEditing } from '@tslite/codemirror/search';
|
|
4
4
|
export { format, formatExpression } from '@tslite/format';
|
|
5
5
|
export { tsliteTokenStyles } from '@tslite/editor';
|
|
@@ -23,10 +23,12 @@ interface PresetOptions {
|
|
|
23
23
|
/**
|
|
24
24
|
* Como o campo se apresenta. Padrão: `"inline"`.
|
|
25
25
|
*
|
|
26
|
-
* `"
|
|
26
|
+
* `"grow"` é o campo de FORMULÁRIO que cresce com o conteúdo: `Enter` termina,
|
|
27
|
+
* `Shift+Enter` quebra, `Tab` navega; régua e busca ficam desligadas, como no
|
|
28
|
+
* `"inline"`. `"block"` é o campo EXPANDIDO (tipicamente num modal): ganha o `Tab` que
|
|
27
29
|
* indenta, a quebra de linha e — por este preset — a régua de linhas.
|
|
28
30
|
*/
|
|
29
|
-
readonly layout?:
|
|
31
|
+
readonly layout?: FieldLayout;
|
|
30
32
|
/**
|
|
31
33
|
* O que o código É. Padrão: `"expression"`.
|
|
32
34
|
*
|
|
@@ -42,6 +44,17 @@ interface PresetOptions {
|
|
|
42
44
|
* comportamento sem pedido. Quem quer, declara.
|
|
43
45
|
*/
|
|
44
46
|
readonly mode?: "expression" | "program" | "template";
|
|
47
|
+
/**
|
|
48
|
+
* ONDE o código está. Padrão: `"mustache"` (texto com ilhas `{{ }}`). Um slot em
|
|
49
|
+
* que o campo inteiro é código (um predicado, um mapper) é `"whole"` — e sem o
|
|
50
|
+
* preset emiti-lo, quem esquecia de passá-lo depois do spread ficava com o
|
|
51
|
+
* `mustache` procurando `{{ }}` num predicado: o campo inteiro virava texto
|
|
52
|
+
* inerte, sem token, sem hover, sem erro.
|
|
53
|
+
*
|
|
54
|
+
* Com `mode: "template"` o preset NÃO o emite: lá quem acha as marcações é o
|
|
55
|
+
* scanner do `@tslite/template`, e a combinação seria contraditória (R14).
|
|
56
|
+
*/
|
|
57
|
+
readonly segmenter?: SegmenterOption;
|
|
45
58
|
/** Régua de linhas. Padrão: ligada no `"block"`, desligada no `"inline"`. */
|
|
46
59
|
readonly gutters?: boolean;
|
|
47
60
|
/** Busca e `Ctrl+D`. Padrão: ligadas no `"block"`, desligadas no `"inline"`. */
|
|
@@ -50,7 +63,7 @@ interface PresetOptions {
|
|
|
50
63
|
readonly extensions?: readonly Extension[];
|
|
51
64
|
}
|
|
52
65
|
/** As props que o preset resolve — o resto (`value`, `onChange`, `env`) é seu. */
|
|
53
|
-
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "gutters" | "format" | "features" | "extensions">;
|
|
66
|
+
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "format" | "features" | "extensions">;
|
|
54
67
|
/**
|
|
55
68
|
* As props de um campo que já nasce certo.
|
|
56
69
|
*
|
package/dist/full.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Extension } from '@codemirror/state';
|
|
2
|
-
import { U as UseExpressionFieldOptions } from './useExpressionField-
|
|
2
|
+
import { F as FieldLayout, S as SegmenterOption, U as UseExpressionFieldOptions } from './useExpressionField-RJzhO-r7.js';
|
|
3
3
|
export { searchEditing } from '@tslite/codemirror/search';
|
|
4
4
|
export { format, formatExpression } from '@tslite/format';
|
|
5
5
|
export { tsliteTokenStyles } from '@tslite/editor';
|
|
@@ -23,10 +23,12 @@ interface PresetOptions {
|
|
|
23
23
|
/**
|
|
24
24
|
* Como o campo se apresenta. Padrão: `"inline"`.
|
|
25
25
|
*
|
|
26
|
-
* `"
|
|
26
|
+
* `"grow"` é o campo de FORMULÁRIO que cresce com o conteúdo: `Enter` termina,
|
|
27
|
+
* `Shift+Enter` quebra, `Tab` navega; régua e busca ficam desligadas, como no
|
|
28
|
+
* `"inline"`. `"block"` é o campo EXPANDIDO (tipicamente num modal): ganha o `Tab` que
|
|
27
29
|
* indenta, a quebra de linha e — por este preset — a régua de linhas.
|
|
28
30
|
*/
|
|
29
|
-
readonly layout?:
|
|
31
|
+
readonly layout?: FieldLayout;
|
|
30
32
|
/**
|
|
31
33
|
* O que o código É. Padrão: `"expression"`.
|
|
32
34
|
*
|
|
@@ -42,6 +44,17 @@ interface PresetOptions {
|
|
|
42
44
|
* comportamento sem pedido. Quem quer, declara.
|
|
43
45
|
*/
|
|
44
46
|
readonly mode?: "expression" | "program" | "template";
|
|
47
|
+
/**
|
|
48
|
+
* ONDE o código está. Padrão: `"mustache"` (texto com ilhas `{{ }}`). Um slot em
|
|
49
|
+
* que o campo inteiro é código (um predicado, um mapper) é `"whole"` — e sem o
|
|
50
|
+
* preset emiti-lo, quem esquecia de passá-lo depois do spread ficava com o
|
|
51
|
+
* `mustache` procurando `{{ }}` num predicado: o campo inteiro virava texto
|
|
52
|
+
* inerte, sem token, sem hover, sem erro.
|
|
53
|
+
*
|
|
54
|
+
* Com `mode: "template"` o preset NÃO o emite: lá quem acha as marcações é o
|
|
55
|
+
* scanner do `@tslite/template`, e a combinação seria contraditória (R14).
|
|
56
|
+
*/
|
|
57
|
+
readonly segmenter?: SegmenterOption;
|
|
45
58
|
/** Régua de linhas. Padrão: ligada no `"block"`, desligada no `"inline"`. */
|
|
46
59
|
readonly gutters?: boolean;
|
|
47
60
|
/** Busca e `Ctrl+D`. Padrão: ligadas no `"block"`, desligadas no `"inline"`. */
|
|
@@ -50,7 +63,7 @@ interface PresetOptions {
|
|
|
50
63
|
readonly extensions?: readonly Extension[];
|
|
51
64
|
}
|
|
52
65
|
/** As props que o preset resolve — o resto (`value`, `onChange`, `env`) é seu. */
|
|
53
|
-
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "gutters" | "format" | "features" | "extensions">;
|
|
66
|
+
type PresetProps = Pick<UseExpressionFieldOptions, "layout" | "mode" | "segmenter" | "gutters" | "format" | "features" | "extensions">;
|
|
54
67
|
/**
|
|
55
68
|
* As props de um campo que já nasce certo.
|
|
56
69
|
*
|
package/dist/full.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {searchEditing}from'@tslite/codemirror/search';export{searchEditing}from'@tslite/codemirror/search';import {format,formatExpression}from'@tslite/format';export{format,formatExpression}from'@tslite/format';import {tsliteTokenStyles}from'@tslite/editor';export{tsliteTokenStyles}from'@tslite/editor';function
|
|
1
|
+
import {searchEditing}from'@tslite/codemirror/search';export{searchEditing}from'@tslite/codemirror/search';import {format,formatExpression}from'@tslite/format';export{format,formatExpression}from'@tslite/format';import {tsliteTokenStyles}from'@tslite/editor';export{tsliteTokenStyles}from'@tslite/editor';function u(t={}){let{dark:s=true,layout:e="inline",mode:o="expression",segmenter:n="mustache",gutters:i=e==="block",search:a=e==="block",extensions:r=[]}=t;return {layout:e,mode:o,...o==="template"?{}:{segmenter:n},gutters:i,format:o==="program"?format:formatExpression,features:{chrome:{dark:s},theme:tsliteTokenStyles},extensions:a?[searchEditing(),...r]:[...r]}}export{u as expressionFieldProps};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';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 ae={mustache:languageService.mustache,whole:languageService.whole},ce=t=>typeof t=="function"?t:ae[t];function A(t){let{env:o,service:c,segmenter:i="mustache",mode:s="expression",profile:l,limits:d,unused:p,format:a}=t;return n__namespace.useMemo(()=>{if(c)return c;if(!o)return null;let m={env:o,...l?{profile:l}:{},...d?{limits:d}:{},...p!==void 0?{unused:p}:{},...a?{format:a}:{}};return s==="template"?editor.createHostService({...m,mode:s}):editor.createHostService({...m,segmenter:ce(i),mode:s})},[c,o,i,s,l,d,p,a])}var Oe=view.EditorView.theme({".cm-scroller":{overflowX:"auto",overflowY:"hidden"},".cm-content":{padding:"6px 8px"},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),z=6,Te=view.EditorView.theme({".cm-scroller":{overflowY:"auto"},".cm-content":{padding:`${z}px 8px`},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),Le=(t,o)=>`${o*t.defaultLineHeight+2*z}px`,we=view.EditorView.theme({"&":{height:"100%"},".cm-scroller":{overflowY:"auto"},".cm-content":{padding:"8px"},"&.cm-focused":{outline:"none"}}),$=t=>t.replace(/\r?\n/g," "),ke=(t,o)=>{if(t===false)return [];let c=o==="block"?{}:{tab:false,indentOnInput:false};return codemirror.codeEditing(typeof t=="object"?{...c,...t}:c)},Ce=t=>t?codemirror.gutters(typeof t=="object"?t:{}):[];function D(t){let{value:o,onChange:c,onCommit:i,layout:s="inline",maxLines:l,wrap:d=s!=="inline",editing:p,gutters:a,readOnly:m=false,placeholder:b,features:I,tooltipParent:L,onTokenAction:V,isTokenActionable:_,definition:w,extensions:ee}=t,h=A(t),k=n__namespace.useRef(null),y=n__namespace.useRef(null),[U,Y]=n__namespace.useState(null),[te,oe]=n__namespace.useState(false),R=n__namespace.useRef({value:o,onChange:c,onCommit:i,onTokenAction:V,isTokenActionable:_});R.current={value:o,onChange:c,onCommit:i,onTokenAction:V,isTokenActionable:_};let C=n__namespace.useCallback(e=>{let{value:r,onCommit:x}=R.current;if(!x)return;let f=e.state.doc.toString();f!==r&&x(f);},[]),u=n__namespace.useRef({service:new state.Compartment,layout:new state.Compartment,editable:new state.Compartment,actions:new state.Compartment}).current,H=n__namespace.useCallback(e=>e?codemirror.languageService(e,{theme:editor.tsliteTokenStyles,...L!==null?{tooltipParent:L??(typeof document<"u"?document.body:void 0)}:{},...I}):[],[I,L]),G=n__namespace.useCallback(e=>autocomplete.completionStatus(e.state)==="active"?autocomplete.acceptCompletion(e)||true:(C(e),true),[C]),P=n__namespace.useCallback((e,r,x,f)=>[e==="block"?[...r?[view.EditorView.lineWrapping]:[],we]:e==="grow"?[...r?[view.EditorView.lineWrapping]:[],Te,state.Prec.highest(view.keymap.of([{key:"Enter",run:G},{key:"Shift-Enter",run:commands.insertNewlineAndIndent}]))]:[codemirror.singleLine,Oe],ke(x,e),Ce(f)],[G]),M=n__namespace.useCallback(()=>{let e=[];return R.current.onTokenAction&&e.push(codemirror.tokenAction({actionable:r=>R.current.isTokenActionable?.(r)??true,onAction:r=>R.current.onTokenAction?.(r)})),w&&h?.definitionAt&&e.push(codemirror.gotoDefinition(w)),e},[w,h]);n__namespace.useEffect(()=>{if(!k.current)return;let e=new view.EditorView({parent:k.current,state:state.EditorState.create({doc:s==="inline"?$(o):o,extensions:[commands.history(),u.service.of(H(h)),u.layout.of(P(s,d,p,a)),u.editable.of(view.EditorView.editable.of(!m)),u.actions.of(M()),...b?[view.placeholder(b)]:[],view.keymap.of([...commands.historyKeymap,...commands.defaultKeymap]),view.EditorView.updateListener.of(r=>{if(r.focusChanged&&oe(r.view.hasFocus),!r.docChanged)return;r.transactions.some(f=>f.annotation(codemirror.externalChange))||R.current.onChange?.(r.state.doc.toString());}),view.EditorView.contentAttributes.of({"aria-label":b??"expression"}),view.EditorView.domEventHandlers({blur:(r,x)=>{let f=r.relatedTarget;return f instanceof Element&&(x.dom.contains(f)||f.closest(".cm-tooltip"))||C(x),false}}),...ee??[]]})});return y.current=e,Y(e),()=>{e.destroy(),y.current=null,Y(null);}},[]),n__namespace.useEffect(()=>{y.current?.dispatch({effects:u.service.reconfigure(H(h))});},[h,H,u]),n__namespace.useEffect(()=>{y.current?.dispatch({effects:u.layout.reconfigure(P(s,d,p,a))});},[s,d,p,a,P,u]),n__namespace.useEffect(()=>{y.current?.dispatch({effects:u.editable.reconfigure(view.EditorView.editable.of(!m))});},[m,u]),n__namespace.useEffect(()=>{let e=y.current;e&&(e.scrollDOM.style.maxHeight=s==="grow"&&l!==void 0&&l>0?Le(e,l):"");},[s,l,U]),n__namespace.useEffect(()=>{y.current?.dispatch({effects:u.actions.reconfigure(M())});},[M,u]),n__namespace.useEffect(()=>{let e=y.current;if(!e)return;let r=s==="inline"?$(o):o;if(r===e.state.doc.toString())return;let{anchor:x,head:f}=e.state.selection.main,N=re=>Math.min(re,r.length);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:r},selection:{anchor:N(x),head:N(f)},annotations:codemirror.externalChange.of(true)});},[o,s]);let ne=n__namespace.useCallback(()=>y.current?.focus(),[]);return {ref:k,view:U,focused:te,service:h,focus:ne}}var X=n__namespace.createContext(null);function J(){let t=n__namespace.useContext(X);if(!t)throw new Error("useFieldContext must be used inside <ExpressionField.Root>");return t}var He=["value","onChange","onCommit","layout","maxLines","wrap","editing","gutters","readOnly","placeholder","features","tooltipParent","onTokenAction","isTokenActionable","definition","extensions","env","service","segmenter","mode","profile","limits","unused","format"];var Q=n__namespace.forwardRef(function(o,c){let{children:i,...s}=o,l={},d={};for(let[a,m]of Object.entries(s))(He.includes(a)?l:d)[a]=m;let p=D(l);return jsxRuntime.jsx(X.Provider,{value:p,children:jsxRuntime.jsx("div",{ref:c,...d,children:typeof i=="function"?i(p):i})})}),Z=n__namespace.forwardRef(function(o,c){let i=J();return jsxRuntime.jsx("div",{ref:i.ref,...o})}),q=n__namespace.forwardRef(function({children:o,...c},i){return jsxRuntime.jsx("button",{ref:i,type:"button",...c,children:o})}),S={Root:Q,Editor:Z,ExpandTrigger:q};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)"},Pe=["--foreground","--muted-foreground","--border","--ring","--input","--destructive","--font-mono","--muted","--popover","--popover-foreground","--primary","--primary-foreground","--secondary","--accent"];var Me=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 Ae({invalid:t,className:o,style:c,onExpand:i,expandIcon:s,multiline:l,layout:d,...p}){let a=d??(l?"block":"inline");return jsxRuntime.jsx(S.Root,{...p,layout:a,className:o,children:m=>jsxRuntime.jsxs("div",{style:{position:"relative",border:`1px solid ${t?E.destructive:m.focused?E.ring:E.border}`,borderRadius:"6px",backgroundColor:E.input,color:E.fg,fontFamily:E.font,fontSize:"13px",overflow:"hidden",...a==="block"?{height:"100%",display:"flex",flexDirection:"column"}:{},...c},children:[jsxRuntime.jsx(S.Editor,{style:a==="block"?{flex:1,minHeight:0}:a==="grow"?{paddingRight:i?"28px":void 0}:{paddingRight:i?"24px":void 0}}),i&&jsxRuntime.jsx(S.ExpandTrigger,{onClick:i,"aria-label":"Expandir",title:"Expandir",onMouseEnter:b=>b.currentTarget.style.opacity="1",onMouseLeave:b=>b.currentTarget.style.opacity="0.55",style:{position:"absolute",top:a==="inline"?"50%":"6px",right:"4px",transform:a==="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:s??Me})]})})}exports.CSS_VARS=Pe;exports.ExpressionField=S;exports.ExpressionFieldEditor=Z;exports.ExpressionFieldExpandTrigger=q;exports.ExpressionFieldRoot=Q;exports.ExpressionInput=Ae;exports.V=E;exports.useExpressionField=D;exports.useFieldContext=J;exports.useLanguageService=A;
|
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, a as useLanguageService } from './useExpressionField-
|
|
2
|
+
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-RJzhO-r7.cjs';
|
|
3
|
+
export { F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField, a as useLanguageService } from './useExpressionField-RJzhO-r7.cjs';
|
|
4
4
|
export { TokenActionTarget } from '@tslite/codemirror';
|
|
5
5
|
import '@codemirror/state';
|
|
6
6
|
import '@codemirror/view';
|
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, a as useLanguageService } from './useExpressionField-
|
|
2
|
+
import { U as UseExpressionFieldOptions, E as ExpressionFieldHandle } from './useExpressionField-RJzhO-r7.js';
|
|
3
|
+
export { F as FieldLayout, L as LanguageServiceOptions, S as SegmenterOption, u as useExpressionField, a as useLanguageService } from './useExpressionField-RJzhO-r7.js';
|
|
4
4
|
export { TokenActionTarget } from '@tslite/codemirror';
|
|
5
5
|
import '@codemirror/state';
|
|
6
6
|
import '@codemirror/view';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
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,externalChange,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 ae={mustache:mustache,whole:whole},ce=t=>typeof t=="function"?t:ae[t];function A(t){let{env:o,service:c,segmenter:i="mustache",mode:s="expression",profile:l,limits:d,unused:p,format:a}=t;return n.useMemo(()=>{if(c)return c;if(!o)return null;let m={env:o,...l?{profile:l}:{},...d?{limits:d}:{},...p!==void 0?{unused:p}:{},...a?{format:a}:{}};return s==="template"?createHostService({...m,mode:s}):createHostService({...m,segmenter:ce(i),mode:s})},[c,o,i,s,l,d,p,a])}var Oe=EditorView.theme({".cm-scroller":{overflowX:"auto",overflowY:"hidden"},".cm-content":{padding:"6px 8px"},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),z=6,Te=EditorView.theme({".cm-scroller":{overflowY:"auto"},".cm-content":{padding:`${z}px 8px`},".cm-line":{padding:"0"},"&.cm-focused":{outline:"none"}}),Le=(t,o)=>`${o*t.defaultLineHeight+2*z}px`,we=EditorView.theme({"&":{height:"100%"},".cm-scroller":{overflowY:"auto"},".cm-content":{padding:"8px"},"&.cm-focused":{outline:"none"}}),$=t=>t.replace(/\r?\n/g," "),ke=(t,o)=>{if(t===false)return [];let c=o==="block"?{}:{tab:false,indentOnInput:false};return codeEditing(typeof t=="object"?{...c,...t}:c)},Ce=t=>t?gutters(typeof t=="object"?t:{}):[];function D(t){let{value:o,onChange:c,onCommit:i,layout:s="inline",maxLines:l,wrap:d=s!=="inline",editing:p,gutters:a,readOnly:m=false,placeholder:b,features:I,tooltipParent:L,onTokenAction:V,isTokenActionable:_,definition:w,extensions:ee}=t,h=A(t),k=n.useRef(null),y=n.useRef(null),[U,Y]=n.useState(null),[te,oe]=n.useState(false),R=n.useRef({value:o,onChange:c,onCommit:i,onTokenAction:V,isTokenActionable:_});R.current={value:o,onChange:c,onCommit:i,onTokenAction:V,isTokenActionable:_};let C=n.useCallback(e=>{let{value:r,onCommit:x}=R.current;if(!x)return;let f=e.state.doc.toString();f!==r&&x(f);},[]),u=n.useRef({service:new Compartment,layout:new Compartment,editable:new Compartment,actions:new Compartment}).current,H=n.useCallback(e=>e?languageService(e,{theme:tsliteTokenStyles,...L!==null?{tooltipParent:L??(typeof document<"u"?document.body:void 0)}:{},...I}):[],[I,L]),G=n.useCallback(e=>completionStatus(e.state)==="active"?acceptCompletion(e)||true:(C(e),true),[C]),P=n.useCallback((e,r,x,f)=>[e==="block"?[...r?[EditorView.lineWrapping]:[],we]:e==="grow"?[...r?[EditorView.lineWrapping]:[],Te,Prec.highest(keymap.of([{key:"Enter",run:G},{key:"Shift-Enter",run:insertNewlineAndIndent}]))]:[singleLine,Oe],ke(x,e),Ce(f)],[G]),M=n.useCallback(()=>{let e=[];return R.current.onTokenAction&&e.push(tokenAction({actionable:r=>R.current.isTokenActionable?.(r)??true,onAction:r=>R.current.onTokenAction?.(r)})),w&&h?.definitionAt&&e.push(gotoDefinition(w)),e},[w,h]);n.useEffect(()=>{if(!k.current)return;let e=new EditorView({parent:k.current,state:EditorState.create({doc:s==="inline"?$(o):o,extensions:[history(),u.service.of(H(h)),u.layout.of(P(s,d,p,a)),u.editable.of(EditorView.editable.of(!m)),u.actions.of(M()),...b?[placeholder(b)]:[],keymap.of([...historyKeymap,...defaultKeymap]),EditorView.updateListener.of(r=>{if(r.focusChanged&&oe(r.view.hasFocus),!r.docChanged)return;r.transactions.some(f=>f.annotation(externalChange))||R.current.onChange?.(r.state.doc.toString());}),EditorView.contentAttributes.of({"aria-label":b??"expression"}),EditorView.domEventHandlers({blur:(r,x)=>{let f=r.relatedTarget;return f instanceof Element&&(x.dom.contains(f)||f.closest(".cm-tooltip"))||C(x),false}}),...ee??[]]})});return y.current=e,Y(e),()=>{e.destroy(),y.current=null,Y(null);}},[]),n.useEffect(()=>{y.current?.dispatch({effects:u.service.reconfigure(H(h))});},[h,H,u]),n.useEffect(()=>{y.current?.dispatch({effects:u.layout.reconfigure(P(s,d,p,a))});},[s,d,p,a,P,u]),n.useEffect(()=>{y.current?.dispatch({effects:u.editable.reconfigure(EditorView.editable.of(!m))});},[m,u]),n.useEffect(()=>{let e=y.current;e&&(e.scrollDOM.style.maxHeight=s==="grow"&&l!==void 0&&l>0?Le(e,l):"");},[s,l,U]),n.useEffect(()=>{y.current?.dispatch({effects:u.actions.reconfigure(M())});},[M,u]),n.useEffect(()=>{let e=y.current;if(!e)return;let r=s==="inline"?$(o):o;if(r===e.state.doc.toString())return;let{anchor:x,head:f}=e.state.selection.main,N=re=>Math.min(re,r.length);e.dispatch({changes:{from:0,to:e.state.doc.length,insert:r},selection:{anchor:N(x),head:N(f)},annotations:externalChange.of(true)});},[o,s]);let ne=n.useCallback(()=>y.current?.focus(),[]);return {ref:k,view:U,focused:te,service:h,focus:ne}}var X=n.createContext(null);function J(){let t=n.useContext(X);if(!t)throw new Error("useFieldContext must be used inside <ExpressionField.Root>");return t}var He=["value","onChange","onCommit","layout","maxLines","wrap","editing","gutters","readOnly","placeholder","features","tooltipParent","onTokenAction","isTokenActionable","definition","extensions","env","service","segmenter","mode","profile","limits","unused","format"];var Q=n.forwardRef(function(o,c){let{children:i,...s}=o,l={},d={};for(let[a,m]of Object.entries(s))(He.includes(a)?l:d)[a]=m;let p=D(l);return jsx(X.Provider,{value:p,children:jsx("div",{ref:c,...d,children:typeof i=="function"?i(p):i})})}),Z=n.forwardRef(function(o,c){let i=J();return jsx("div",{ref:i.ref,...o})}),q=n.forwardRef(function({children:o,...c},i){return jsx("button",{ref:i,type:"button",...c,children:o})}),S={Root:Q,Editor:Z,ExpandTrigger:q};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)"},Pe=["--foreground","--muted-foreground","--border","--ring","--input","--destructive","--font-mono","--muted","--popover","--popover-foreground","--primary","--primary-foreground","--secondary","--accent"];var Me=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 Ae({invalid:t,className:o,style:c,onExpand:i,expandIcon:s,multiline:l,layout:d,...p}){let a=d??(l?"block":"inline");return jsx(S.Root,{...p,layout:a,className:o,children:m=>jsxs("div",{style:{position:"relative",border:`1px solid ${t?E.destructive:m.focused?E.ring:E.border}`,borderRadius:"6px",backgroundColor:E.input,color:E.fg,fontFamily:E.font,fontSize:"13px",overflow:"hidden",...a==="block"?{height:"100%",display:"flex",flexDirection:"column"}:{},...c},children:[jsx(S.Editor,{style:a==="block"?{flex:1,minHeight:0}:a==="grow"?{paddingRight:i?"28px":void 0}:{paddingRight:i?"24px":void 0}}),i&&jsx(S.ExpandTrigger,{onClick:i,"aria-label":"Expandir",title:"Expandir",onMouseEnter:b=>b.currentTarget.style.opacity="1",onMouseLeave:b=>b.currentTarget.style.opacity="0.55",style:{position:"absolute",top:a==="inline"?"50%":"6px",right:"4px",transform:a==="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:s??Me})]})})}export{Pe as CSS_VARS,S as ExpressionField,Z as ExpressionFieldEditor,q as ExpressionFieldExpandTrigger,Q as ExpressionFieldRoot,Ae as ExpressionInput,E as V,D as useExpressionField,J as useFieldContext,A as useLanguageService};
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
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
|
-
import {
|
|
5
|
+
import { Segmenter, LanguageService, Token } from '@tslite/language-service';
|
|
6
6
|
import { HostServiceOptions } from '@tslite/editor';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -18,7 +18,7 @@ interface LanguageServiceOptions {
|
|
|
18
18
|
/**
|
|
19
19
|
* O ambiente de tipos — o shape dos dados no escopo das expressões.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* **Memoize-o.** Um objeto novo a cada render reconstrói o serviço e joga
|
|
22
22
|
* fora o cache de análise. `useMemo` no seu lado resolve.
|
|
23
23
|
*/
|
|
24
24
|
readonly env?: HostServiceOptions["env"];
|
|
@@ -77,19 +77,48 @@ declare function useLanguageService(options: LanguageServiceOptions): LanguageSe
|
|
|
77
77
|
* Como o campo se APRESENTA — ortogonal ao que ele contém.
|
|
78
78
|
*
|
|
79
79
|
* - `"inline"` — uma linha, estilo input: sem quebra, rolagem horizontal;
|
|
80
|
-
* - `"
|
|
80
|
+
* - `"grow"` — um campo de formulário que cresce com o conteúdo (até `maxLines`,
|
|
81
|
+
* e depois rola por dentro): quebra de linha, `Tab` navega, `Enter` TERMINA
|
|
82
|
+
* (commit) e `Shift+Enter` quebra. Um valor com quebras é preservado;
|
|
83
|
+
* - `"block"` — várias linhas, estilo editor: quebra de linha e rolagem vertical,
|
|
84
|
+
* `Tab` indenta, `Enter` quebra.
|
|
81
85
|
*/
|
|
82
|
-
type FieldLayout = "inline" | "block";
|
|
86
|
+
type FieldLayout = "inline" | "grow" | "block";
|
|
83
87
|
interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
84
88
|
/** O texto do campo (controlado). */
|
|
85
89
|
readonly value: string;
|
|
86
90
|
/** Chamado a cada edição do USUÁRIO — nunca por sincronização externa. */
|
|
87
91
|
readonly onChange?: (value: string) => void;
|
|
92
|
+
/**
|
|
93
|
+
* O autor TERMINOU: o foco saiu do campo, ou o `Enter` terminou (layout
|
|
94
|
+
* `"grow"`). Recebe o texto do editor, e só dispara quando ele difere do
|
|
95
|
+
* `value` recebido.
|
|
96
|
+
*
|
|
97
|
+
* É o par `onValueChange`/`onValueCommit` do Slider do Radix. Quem usa
|
|
98
|
+
* `onCommit` passa como `value` o valor COMMITADO do documento: o documento do
|
|
99
|
+
* CodeMirror é o rascunho, e não há estado a mais no consumidor — uma entrada
|
|
100
|
+
* de histórico por commit, não por tecla. Quando o valor muda por baixo (um
|
|
101
|
+
* undo do documento, uma edição vinda de outra superfície), a sincronização
|
|
102
|
+
* externa reassenta o editor. `onChange` continua como está; os dois convivem
|
|
103
|
+
* (um preview ao vivo e o commit no fim).
|
|
104
|
+
*
|
|
105
|
+
* O foco que vai para um tooltip do próprio campo (o dropdown, o "Quick Fix…")
|
|
106
|
+
* não é o autor terminando, e não commita.
|
|
107
|
+
*/
|
|
108
|
+
readonly onCommit?: (text: string) => void;
|
|
88
109
|
/** Como o campo se apresenta. Padrão: `"inline"`. */
|
|
89
110
|
readonly layout?: FieldLayout;
|
|
90
111
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
112
|
+
* O teto do layout `"grow"`, em LINHAS: até ele o campo cresce com o conteúdo;
|
|
113
|
+
* a partir dele, rola por dentro. Sem padrão — quanto espaço um campo pode
|
|
114
|
+
* ocupar é decisão do layout de quem monta a tela (é a regra do `maxRows` do
|
|
115
|
+
* MUI e do `field-sizing: content` do CSS: o campo cresce, e para onde o
|
|
116
|
+
* `max-height` de quem monta disser). Ignorado nos outros layouts.
|
|
117
|
+
*/
|
|
118
|
+
readonly maxLines?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Quebrar linha longa em vez de rolar na horizontal. Padrão: `true` nos
|
|
121
|
+
* layouts `"grow"` e `"block"`.
|
|
93
122
|
*
|
|
94
123
|
* É opção à parte do `layout` porque são decisões diferentes: um CAMPO de
|
|
95
124
|
* várias linhas quer quebrar (o texto é o conteúdo); um editor de ARQUIVO
|
|
@@ -105,7 +134,7 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
105
134
|
* | layout | `Tab` | por quê |
|
|
106
135
|
* | --- | --- | --- |
|
|
107
136
|
* | `"block"` | indenta | é um editor: não há para onde o foco ir |
|
|
108
|
-
* | `"inline"` | **navega** | num campo de formulário, roubar o `Tab` prende o teclado — o usuário não sai sem o mouse |
|
|
137
|
+
* | `"inline"` · `"grow"` | **navega** | num campo de formulário, roubar o `Tab` prende o teclado — o usuário não sai sem o mouse |
|
|
109
138
|
*
|
|
110
139
|
* Passe `false` para não instalar nada, ou um objeto para ajustar (ele é
|
|
111
140
|
* mesclado sobre o padrão do layout).
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
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
|
-
import {
|
|
5
|
+
import { Segmenter, LanguageService, Token } from '@tslite/language-service';
|
|
6
6
|
import { HostServiceOptions } from '@tslite/editor';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -18,7 +18,7 @@ interface LanguageServiceOptions {
|
|
|
18
18
|
/**
|
|
19
19
|
* O ambiente de tipos — o shape dos dados no escopo das expressões.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* **Memoize-o.** Um objeto novo a cada render reconstrói o serviço e joga
|
|
22
22
|
* fora o cache de análise. `useMemo` no seu lado resolve.
|
|
23
23
|
*/
|
|
24
24
|
readonly env?: HostServiceOptions["env"];
|
|
@@ -77,19 +77,48 @@ declare function useLanguageService(options: LanguageServiceOptions): LanguageSe
|
|
|
77
77
|
* Como o campo se APRESENTA — ortogonal ao que ele contém.
|
|
78
78
|
*
|
|
79
79
|
* - `"inline"` — uma linha, estilo input: sem quebra, rolagem horizontal;
|
|
80
|
-
* - `"
|
|
80
|
+
* - `"grow"` — um campo de formulário que cresce com o conteúdo (até `maxLines`,
|
|
81
|
+
* e depois rola por dentro): quebra de linha, `Tab` navega, `Enter` TERMINA
|
|
82
|
+
* (commit) e `Shift+Enter` quebra. Um valor com quebras é preservado;
|
|
83
|
+
* - `"block"` — várias linhas, estilo editor: quebra de linha e rolagem vertical,
|
|
84
|
+
* `Tab` indenta, `Enter` quebra.
|
|
81
85
|
*/
|
|
82
|
-
type FieldLayout = "inline" | "block";
|
|
86
|
+
type FieldLayout = "inline" | "grow" | "block";
|
|
83
87
|
interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
84
88
|
/** O texto do campo (controlado). */
|
|
85
89
|
readonly value: string;
|
|
86
90
|
/** Chamado a cada edição do USUÁRIO — nunca por sincronização externa. */
|
|
87
91
|
readonly onChange?: (value: string) => void;
|
|
92
|
+
/**
|
|
93
|
+
* O autor TERMINOU: o foco saiu do campo, ou o `Enter` terminou (layout
|
|
94
|
+
* `"grow"`). Recebe o texto do editor, e só dispara quando ele difere do
|
|
95
|
+
* `value` recebido.
|
|
96
|
+
*
|
|
97
|
+
* É o par `onValueChange`/`onValueCommit` do Slider do Radix. Quem usa
|
|
98
|
+
* `onCommit` passa como `value` o valor COMMITADO do documento: o documento do
|
|
99
|
+
* CodeMirror é o rascunho, e não há estado a mais no consumidor — uma entrada
|
|
100
|
+
* de histórico por commit, não por tecla. Quando o valor muda por baixo (um
|
|
101
|
+
* undo do documento, uma edição vinda de outra superfície), a sincronização
|
|
102
|
+
* externa reassenta o editor. `onChange` continua como está; os dois convivem
|
|
103
|
+
* (um preview ao vivo e o commit no fim).
|
|
104
|
+
*
|
|
105
|
+
* O foco que vai para um tooltip do próprio campo (o dropdown, o "Quick Fix…")
|
|
106
|
+
* não é o autor terminando, e não commita.
|
|
107
|
+
*/
|
|
108
|
+
readonly onCommit?: (text: string) => void;
|
|
88
109
|
/** Como o campo se apresenta. Padrão: `"inline"`. */
|
|
89
110
|
readonly layout?: FieldLayout;
|
|
90
111
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
112
|
+
* O teto do layout `"grow"`, em LINHAS: até ele o campo cresce com o conteúdo;
|
|
113
|
+
* a partir dele, rola por dentro. Sem padrão — quanto espaço um campo pode
|
|
114
|
+
* ocupar é decisão do layout de quem monta a tela (é a regra do `maxRows` do
|
|
115
|
+
* MUI e do `field-sizing: content` do CSS: o campo cresce, e para onde o
|
|
116
|
+
* `max-height` de quem monta disser). Ignorado nos outros layouts.
|
|
117
|
+
*/
|
|
118
|
+
readonly maxLines?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Quebrar linha longa em vez de rolar na horizontal. Padrão: `true` nos
|
|
121
|
+
* layouts `"grow"` e `"block"`.
|
|
93
122
|
*
|
|
94
123
|
* É opção à parte do `layout` porque são decisões diferentes: um CAMPO de
|
|
95
124
|
* várias linhas quer quebrar (o texto é o conteúdo); um editor de ARQUIVO
|
|
@@ -105,7 +134,7 @@ interface UseExpressionFieldOptions extends LanguageServiceOptions {
|
|
|
105
134
|
* | layout | `Tab` | por quê |
|
|
106
135
|
* | --- | --- | --- |
|
|
107
136
|
* | `"block"` | indenta | é um editor: não há para onde o foco ir |
|
|
108
|
-
* | `"inline"` | **navega** | num campo de formulário, roubar o `Tab` prende o teclado — o usuário não sai sem o mouse |
|
|
137
|
+
* | `"inline"` · `"grow"` | **navega** | num campo de formulário, roubar o `Tab` prende o teclado — o usuário não sai sem o mouse |
|
|
109
138
|
*
|
|
110
139
|
* Passe `false` para não instalar nada, ou um objeto para ajustar (ele é
|
|
111
140
|
* mesclado sobre o padrão do layout).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tslite/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
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 checker.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@tslite/codemirror": "0.3.
|
|
51
|
-
"@tslite/editor": "0.6.
|
|
52
|
-
"@tslite/format": "0.5.
|
|
53
|
-
"@tslite/language-service": "0.
|
|
50
|
+
"@tslite/codemirror": "0.3.2",
|
|
51
|
+
"@tslite/editor": "0.6.10",
|
|
52
|
+
"@tslite/format": "0.5.6",
|
|
53
|
+
"@tslite/language-service": "0.4.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@codemirror/autocomplete": "^6.0.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@types/react-dom": "^18.3.1",
|
|
77
77
|
"react": "^18.3.1",
|
|
78
78
|
"react-dom": "^18.3.1",
|
|
79
|
-
"@tslite/checker": "0.
|
|
79
|
+
"@tslite/checker": "0.11.1"
|
|
80
80
|
},
|
|
81
81
|
"peerDependenciesMeta": {
|
|
82
82
|
"@codemirror/search": {
|