@typix-editor/extension-max-length 1.0.0 → 3.0.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/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client'
2
- var w=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var A=(t,n)=>{for(var a in n)w(t,a,{get:n[a],enumerable:!0})},G=(t,n,a,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let c of B(n))!z.call(t,c)&&c!==a&&w(t,c,{get:()=>n[c],enumerable:!(s=W(n,c))||s.enumerable});return t};var J=t=>G(w({},"__esModule",{value:!0}),t);var U={};A(U,{MaxLengthExtension:()=>M});module.exports=J(U);var $=require("@lexical/react/LexicalComposerContext"),T=require("@lexical/selection"),N=require("@lexical/utils"),g=require("lexical"),u=require("react");function I(t,n,a){switch(a||(t=t.replace(/\s/g,"")),n){case"words":return t.trim().split(/\s+/).filter(s=>s.length>0).length;case"bytes":return new Blob([t]).size;default:if(typeof Intl<"u"&&"Segmenter"in Intl)try{return[...new Intl.Segmenter().segment(t)].length}catch{console.warn("Intl.Segmenter not available, using fallback")}return O(t)}}function O(t){let n=t.match(/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g);return n?n.length:0}function M({maxLength:t,mode:n="characters",onLimitReached:a,onChange:s,warningThreshold:c=.9,onWarning:f,strategy:h="prevent",countWhitespace:d=!0,customCounter:b,debug:L=!1}){let[m]=(0,$.useLexicalComposerContext)(),C=(0,u.useRef)(null),p=(0,u.useRef)(!1),F=(0,u.useRef)({maxLength:t,mode:n,onLimitReached:a,onChange:s,warningThreshold:c,onWarning:f,strategy:h,countWhitespace:d,customCounter:b,debug:L});(0,u.useEffect)(()=>{F.current={maxLength:t,mode:n,onLimitReached:a,onChange:s,warningThreshold:c,onWarning:f,strategy:h,countWhitespace:d,customCounter:b,debug:L}},[t,n,a,s,c,f,h,d,b,L]);let i=(0,u.useCallback)((...E)=>{F.current.debug&&console.log("[MaxLength]",...E)},[]);return(0,u.useEffect)(()=>{i("Registering max length extension",{maxLength:t,mode:n,strategy:h});let E=m.registerNodeTransform(g.RootNode,l=>{let y=(0,g.$getSelection)();if(!(0,g.$isRangeSelection)(y)||!y.isCollapsed())return;let e=F.current,x=m.getEditorState(),R=l.getTextContent(),r=e.customCounter?e.customCounter(R):I(R,e.mode,e.countWhitespace),D=x.read(()=>l.getTextContent()),S=e.customCounter?e.customCounter(D):I(D,e.mode,e.countWhitespace);if(i("Content length",{current:r,previous:S,max:e.maxLength}),r!==S&&e.onChange){let o=e.maxLength-r;e.onChange(r,e.maxLength,o)}let v=Math.floor(e.maxLength*e.warningThreshold);if(r>=v&&r<e.maxLength&&!p.current&&e.onWarning){p.current=!0;let o=e.maxLength-r;i("Warning threshold reached",{currentLength:r,warningLimit:v}),e.onWarning(r,e.maxLength,o)}if(r<v&&(p.current=!1),r>e.maxLength){let o=r-e.maxLength;i("Limit exceeded",{exceeded:o,strategy:e.strategy}),e.onLimitReached&&e.onLimitReached(r,e.maxLength,o);let k=y.anchor;switch(e.strategy){case"prevent":S===e.maxLength&&C.current!==x?(i("Restoring previous state"),C.current=x,(0,N.$restoreEditorState)(m,x)):(i("Trimming from cursor",{amount:o}),(0,T.$trimTextContentFromAnchor)(m,k,o));break;case"trim":i("Trimming from cursor",{amount:o}),(0,T.$trimTextContentFromAnchor)(m,k,o);break;case"truncate":i("Truncating from end",{amount:o}),m.update(()=>{let P=R.slice(0,e.maxLength);l.clear(),l.append(m.parseEditorState(JSON.stringify({root:{children:[{type:"paragraph",children:[{type:"text",text:P}]}]}})).read(()=>l))});break}}});return()=>{i("Unregistering max length extension"),E(),C.current=null,p.current=!1}},[m,i]),null}M.displayName="Typix.MaxLengthExtension";0&&(module.exports={MaxLengthExtension});
2
+ var w=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var z=(t,n)=>{for(var o in n)w(t,o,{get:n[o],enumerable:!0})},A=(t,n,o,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of W(n))!B.call(t,i)&&i!==o&&w(t,i,{get:()=>n[i],enumerable:!(s=P(n,i))||s.enumerable});return t};var G=t=>A(w({},"__esModule",{value:!0}),t);var j={};z(j,{MaxLengthExtension:()=>S});module.exports=G(j);var I=require("@lexical/react/LexicalComposerContext"),y=require("@lexical/selection"),$=require("@lexical/utils"),g=require("lexical"),u=require("react");function N(t,n,o){switch(o||(t=t.replace(/\s/g,"")),n){case"words":return t.trim().split(/\s+/).filter(s=>s.length>0).length;case"bytes":return new Blob([t]).size;default:if(typeof Intl<"u"&&"Segmenter"in Intl)try{return[...new Intl.Segmenter().segment(t)].length}catch{console.warn("Intl.Segmenter not available, using fallback")}return U(t)}}function U(t){let n=t.match(/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g);return n?n.length:0}function S({maxLength:t,mode:n="characters",onLimitReached:o,onChange:s,warningThreshold:i=.9,onWarning:f,strategy:l="prevent",countWhitespace:p=!0,customCounter:d,debug:b=!1}){let[m]=(0,I.useLexicalComposerContext)(),L=(0,u.useRef)(null),h=(0,u.useRef)(!1),C=(0,u.useRef)({maxLength:t,mode:n,onLimitReached:o,onChange:s,warningThreshold:i,onWarning:f,strategy:l,countWhitespace:p,customCounter:d,debug:b});(0,u.useEffect)(()=>{C.current={maxLength:t,mode:n,onLimitReached:o,onChange:s,warningThreshold:i,onWarning:f,strategy:l,countWhitespace:p,customCounter:d,debug:b}},[t,n,o,s,i,f,l,p,d,b]);let c=(0,u.useCallback)((...F)=>{C.current.debug&&console.log("[MaxLength]",...F)},[]);return(0,u.useEffect)(()=>{c("Registering max length extension",{maxLength:t,mode:n,strategy:l});let F=m.registerNodeTransform(g.RootNode,M=>{let E=(0,g.$getSelection)();if(!(0,g.$isRangeSelection)(E)||!E.isCollapsed())return;let e=C.current,x=m.getEditorState(),T=M.getTextContent(),r=e.customCounter?e.customCounter(T):N(T,e.mode,e.countWhitespace),D=x.read(()=>M.getTextContent()),R=e.customCounter?e.customCounter(D):N(D,e.mode,e.countWhitespace);if(c("Content length",{current:r,previous:R,max:e.maxLength}),r!==R&&e.onChange){let a=e.maxLength-r;e.onChange(r,e.maxLength,a)}let v=Math.floor(e.maxLength*e.warningThreshold);if(r>=v&&r<e.maxLength&&!h.current&&e.onWarning){h.current=!0;let a=e.maxLength-r;c("Warning threshold reached",{currentLength:r,warningLimit:v}),e.onWarning(r,e.maxLength,a)}if(r<v&&(h.current=!1),r>e.maxLength){let a=r-e.maxLength;c("Limit exceeded",{exceeded:a,strategy:e.strategy}),e.onLimitReached&&e.onLimitReached(r,e.maxLength,a);let k=E.anchor;switch(e.strategy){case"prevent":R===e.maxLength&&L.current!==x?(c("Restoring previous state"),L.current=x,(0,$.$restoreEditorState)(m,x)):(c("Trimming from cursor",{amount:a}),(0,y.$trimTextContentFromAnchor)(m,k,a));break;case"trim":c("Trimming from cursor",{amount:a}),(0,y.$trimTextContentFromAnchor)(m,k,a);break}}});return()=>{c("Unregistering max length extension"),F(),L.current=null,h.current=!1}},[m,c]),null}S.displayName="Typix.MaxLengthExtension";0&&(module.exports={MaxLengthExtension});
package/dist/index.d.cts CHANGED
@@ -37,9 +37,8 @@ interface MaxLengthExtensionProps {
37
37
  * Strategy when limit is exceeded
38
38
  * @default 'prevent' - Prevents further input
39
39
  * @alternative 'trim' - Trims oldest content
40
- * @alternative 'truncate' - Truncates from cursor position
41
40
  */
42
- strategy?: 'prevent' | 'trim' | 'truncate';
41
+ strategy?: 'prevent' | 'trim';
43
42
  /**
44
43
  * Whether to count whitespace
45
44
  * @default true
package/dist/index.d.ts CHANGED
@@ -37,9 +37,8 @@ interface MaxLengthExtensionProps {
37
37
  * Strategy when limit is exceeded
38
38
  * @default 'prevent' - Prevents further input
39
39
  * @alternative 'trim' - Trims oldest content
40
- * @alternative 'truncate' - Truncates from cursor position
41
40
  */
42
- strategy?: 'prevent' | 'trim' | 'truncate';
41
+ strategy?: 'prevent' | 'trim';
43
42
  /**
44
43
  * Whether to count whitespace
45
44
  * @default true
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client'
2
- import{useLexicalComposerContext as $}from"@lexical/react/LexicalComposerContext";import{$trimTextContentFromAnchor as T}from"@lexical/selection";import{$restoreEditorState as N}from"@lexical/utils";import{$getSelection as P,$isRangeSelection as W,RootNode as B}from"lexical";import{useCallback as z,useEffect as M,useRef as S}from"react";function D(t,a,c){switch(c||(t=t.replace(/\s/g,"")),a){case"words":return t.trim().split(/\s+/).filter(i=>i.length>0).length;case"bytes":return new Blob([t]).size;default:if(typeof Intl<"u"&&"Segmenter"in Intl)try{return[...new Intl.Segmenter().segment(t)].length}catch{console.warn("Intl.Segmenter not available, using fallback")}return A(t)}}function A(t){let a=t.match(/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g);return a?a.length:0}function k({maxLength:t,mode:a="characters",onLimitReached:c,onChange:i,warningThreshold:h=.9,onWarning:p,strategy:m="prevent",countWhitespace:x=!0,customCounter:f,debug:d=!1}){let[s]=$(),b=S(null),g=S(!1),L=S({maxLength:t,mode:a,onLimitReached:c,onChange:i,warningThreshold:h,onWarning:p,strategy:m,countWhitespace:x,customCounter:f,debug:d});M(()=>{L.current={maxLength:t,mode:a,onLimitReached:c,onChange:i,warningThreshold:h,onWarning:p,strategy:m,countWhitespace:x,customCounter:f,debug:d}},[t,a,c,i,h,p,m,x,f,d]);let o=z((...C)=>{L.current.debug&&console.log("[MaxLength]",...C)},[]);return M(()=>{o("Registering max length extension",{maxLength:t,mode:a,strategy:m});let C=s.registerNodeTransform(B,u=>{let F=P();if(!W(F)||!F.isCollapsed())return;let e=L.current,l=s.getEditorState(),E=u.getTextContent(),n=e.customCounter?e.customCounter(E):D(E,e.mode,e.countWhitespace),v=l.read(()=>u.getTextContent()),y=e.customCounter?e.customCounter(v):D(v,e.mode,e.countWhitespace);if(o("Content length",{current:n,previous:y,max:e.maxLength}),n!==y&&e.onChange){let r=e.maxLength-n;e.onChange(n,e.maxLength,r)}let R=Math.floor(e.maxLength*e.warningThreshold);if(n>=R&&n<e.maxLength&&!g.current&&e.onWarning){g.current=!0;let r=e.maxLength-n;o("Warning threshold reached",{currentLength:n,warningLimit:R}),e.onWarning(n,e.maxLength,r)}if(n<R&&(g.current=!1),n>e.maxLength){let r=n-e.maxLength;o("Limit exceeded",{exceeded:r,strategy:e.strategy}),e.onLimitReached&&e.onLimitReached(n,e.maxLength,r);let w=F.anchor;switch(e.strategy){case"prevent":y===e.maxLength&&b.current!==l?(o("Restoring previous state"),b.current=l,N(s,l)):(o("Trimming from cursor",{amount:r}),T(s,w,r));break;case"trim":o("Trimming from cursor",{amount:r}),T(s,w,r);break;case"truncate":o("Truncating from end",{amount:r}),s.update(()=>{let I=E.slice(0,e.maxLength);u.clear(),u.append(s.parseEditorState(JSON.stringify({root:{children:[{type:"paragraph",children:[{type:"text",text:I}]}]}})).read(()=>u))});break}}});return()=>{o("Unregistering max length extension"),C(),b.current=null,g.current=!1}},[s,o]),null}k.displayName="Typix.MaxLengthExtension";export{k as MaxLengthExtension};
2
+ import{useLexicalComposerContext as N}from"@lexical/react/LexicalComposerContext";import{$trimTextContentFromAnchor as M}from"@lexical/selection";import{$restoreEditorState as I}from"@lexical/utils";import{$getSelection as $,$isRangeSelection as P,RootNode as W}from"lexical";import{useCallback as B,useEffect as T,useRef as R}from"react";function D(t,o,c){switch(c||(t=t.replace(/\s/g,"")),o){case"words":return t.trim().split(/\s+/).filter(a=>a.length>0).length;case"bytes":return new Blob([t]).size;default:if(typeof Intl<"u"&&"Segmenter"in Intl)try{return[...new Intl.Segmenter().segment(t)].length}catch{console.warn("Intl.Segmenter not available, using fallback")}return z(t)}}function z(t){let o=t.match(/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g);return o?o.length:0}function k({maxLength:t,mode:o="characters",onLimitReached:c,onChange:a,warningThreshold:l=.9,onWarning:h,strategy:u="prevent",countWhitespace:x=!0,customCounter:f,debug:p=!1}){let[i]=N(),d=R(null),m=R(!1),b=R({maxLength:t,mode:o,onLimitReached:c,onChange:a,warningThreshold:l,onWarning:h,strategy:u,countWhitespace:x,customCounter:f,debug:p});T(()=>{b.current={maxLength:t,mode:o,onLimitReached:c,onChange:a,warningThreshold:l,onWarning:h,strategy:u,countWhitespace:x,customCounter:f,debug:p}},[t,o,c,a,l,h,u,x,f,p]);let s=B((...L)=>{b.current.debug&&console.log("[MaxLength]",...L)},[]);return T(()=>{s("Registering max length extension",{maxLength:t,mode:o,strategy:u});let L=i.registerNodeTransform(W,v=>{let C=$();if(!P(C)||!C.isCollapsed())return;let e=b.current,g=i.getEditorState(),w=v.getTextContent(),n=e.customCounter?e.customCounter(w):D(w,e.mode,e.countWhitespace),y=g.read(()=>v.getTextContent()),F=e.customCounter?e.customCounter(y):D(y,e.mode,e.countWhitespace);if(s("Content length",{current:n,previous:F,max:e.maxLength}),n!==F&&e.onChange){let r=e.maxLength-n;e.onChange(n,e.maxLength,r)}let E=Math.floor(e.maxLength*e.warningThreshold);if(n>=E&&n<e.maxLength&&!m.current&&e.onWarning){m.current=!0;let r=e.maxLength-n;s("Warning threshold reached",{currentLength:n,warningLimit:E}),e.onWarning(n,e.maxLength,r)}if(n<E&&(m.current=!1),n>e.maxLength){let r=n-e.maxLength;s("Limit exceeded",{exceeded:r,strategy:e.strategy}),e.onLimitReached&&e.onLimitReached(n,e.maxLength,r);let S=C.anchor;switch(e.strategy){case"prevent":F===e.maxLength&&d.current!==g?(s("Restoring previous state"),d.current=g,I(i,g)):(s("Trimming from cursor",{amount:r}),M(i,S,r));break;case"trim":s("Trimming from cursor",{amount:r}),M(i,S,r);break}}});return()=>{s("Unregistering max length extension"),L(),d.current=null,m.current=!1}},[i,s]),null}k.displayName="Typix.MaxLengthExtension";export{k as MaxLengthExtension};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typix-editor/extension-max-length",
3
- "version": "1.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "Max length extension for Typix",
5
5
  "keywords": [],
6
6
  "author": "Diyorbek Juraev <mrdiyorbekjuraev@gmail.com>",
@@ -27,7 +27,7 @@
27
27
  "peerDependencies": {
28
28
  "react": "^18.2.0 || ^19.0.0-0",
29
29
  "react-dom": "^18.2.0 || ^19.0.0-0",
30
- "@typix-editor/react": "2.0.1"
30
+ "@typix-editor/react": "3.0.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@lexical/react": "^0.39.0",