efficient-easel 0.98.0 → 0.99.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/README.md CHANGED
@@ -214,20 +214,28 @@ email. Framework-free: no React, no DOM, no imports.
214
214
  | `~~x~~` | strikethrough | yes |
215
215
  | `[words](href)` | a link — `http`, `https`, `mailto`, `tel` or no scheme only | yes |
216
216
  | `- ` at the start of a line | a bullet line, one level | yes |
217
+ | `1. ` at the start of a line | a numbered line, one level: 1-3 digits, `. `, words; the number is kept as typed | yes |
218
+ | `[x]{underline}`, `[x]{sup}`, `[x]{sub}` | underline, superscript, subscript (tree only) | not yet — `applyMark` writes them; the buttons come with the final text box |
219
+ | `[x]{color=name}` | a theme colour, by name only (`isColorName`; never a hex) (tree only) | not yet — `applyColor` writes it |
217
220
  | `@@x@@`, `++x++` | Emphasis, Strong (the storefront's old word styles) | no — read only |
218
221
  | `*x*`, `#x#`, `[x]` | legacy accent, bold, italic (per product set) | no — read only |
219
222
 
220
223
  The three names a merchant sees are in `MARK_NAMES`. A run never crosses a line
221
- break, and a run may hold one more run or link (`**bold _with italic_**`); a third
222
- level stays as typed.
224
+ break, and runs, spans and links nest up to four levels
225
+ (`[**_[x]{sup}_**]{color=accent}`); a fifth stays as typed. Any block after `]`
226
+ that is not exactly one of the four (`[x]{foo}`, `[x]{color=#f00}`,
227
+ `[x]{{first_name}}`) is plain text. The spans and the numbered line are read by
228
+ `parseMarkup` only: `tokenizeInline` keeps them as text, so a renderer that has
229
+ not learned them prints the delimiters.
223
230
 
224
231
  | Export | Notes |
225
232
  |---|---|
226
233
  | `parseMarkup(value, rules)` → `MarkupLine[]` | The whole grammar as a tree. Each run keeps the delimiters that were saved. |
227
- | `serializeMarkup(lines)` | The inverse: `serializeMarkup(parseMarkup(s, rules)) === s`, for every string. Pinned by `tests/markup-round-trip.test.ts` (made-up strings in the shape of saved copy). All 917 saved production strings were checked once, off-repo, on 2026-09-29 (editor-shell #89). |
234
+ | `serializeMarkup(lines)` | The inverse: `serializeMarkup(parseMarkup(s, rules)) === s`, for every string. Pinned by `tests/markup-round-trip.test.ts` (made-up strings in the shape of saved copy). All 917 saved production strings were checked off-repo on 2026-09-29 (editor-shell #89), and again for the spans and numbered lines on 2026-10-06 (E1). |
228
235
  | `isSafeLinkHref(href)` | The link rule. Call it before writing any `href`. |
229
236
  | `tokenizeInline(value, rules)`, `stripInline` | The flat reading older renderers use: runs only, no links, no nesting. |
230
237
  | `applyMark(text, start, end, style)`, `MARKUP_TOOLS`, `markupTools`, `COPY_FIELD_TOOLS` | The writer behind a toolbar button, and the button descriptors. |
238
+ | `applyColor(text, start, end, name)`, `isColorName`, `spanFor` | A colour carries a name, so it has its own writer: it writes, renames and (`null`) takes off `[x]{color=name}`, and changes nothing for a name `isColorName` refuses. |
231
239
  | `STANDARD_MARKUP`, `STOREFRONT_MARKUP`, `CAMPAIGN_MARKUP` | The rule sets. The last two add each product's legacy runs. |
232
240
 
233
241
  ## The edit lock — two operators, one document
@@ -1 +1 @@
1
- import{DEFAULT_PICK_WORDS as o}from"./chunk-ZAOM6PFH.js";import{DEFAULT_STYLE_CLIPBOARD_WORDS as r}from"./chunk-6WY6ZXJG.js";import{DEFAULT_CANVAS_WORDS as t}from"./chunk-GGTPNGFJ.js";import{DEFAULT_FIELDS_WORDS as m}from"./chunk-SUO5627P.js";import{DEFAULT_TREE_WORDS as n}from"./chunk-H4B72XCJ.js";import{DEFAULT_PANEL_WORDS as c}from"./chunk-7A7O2JWQ.js";import{DEFAULT_NODE_MENU_WORDS as f}from"./chunk-WK3AFPXY.js";import{DEFAULT_SAVE_WORDS as p}from"./chunk-H6DDIBQ4.js";import{DEFAULT_CHROME_WORDS as s,DEFAULT_NOTICE_WORDS as i}from"./chunk-KDIVA6WD.js";import{DEFAULT_LOCK_WORDS as u}from"./chunk-RE4LP46F.js";import{DEFAULT_RAIL_WORDS as e}from"./chunk-2OAZYSWJ.js";import{DEFAULT_COPY_WORDS as k}from"./chunk-2LUSK32B.js";import{DEFAULT_DRAG_WORDS as j}from"./chunk-O2NLQBFX.js";var h={notice:i,lock:u,save:p,chrome:s,rail:e,tree:n,panel:c,fields:m,pick:o,drag:j,menu:f,styleClipboard:r,copy:k,canvas:t},l=o=>"object"==typeof o&&null!==o;function a(o,r){const t={};for(const m of Object.keys(o)){const n=o[m],c=r[m];null==c?t[m]=n:l(n)?t[m]=l(c)?a(n,c):n:t[m]=typeof c==typeof n?c:n}return t}function y(o,r){return r?a(o,r):o}export{h as DEFAULT_EDITOR_STRINGS,y as mergeEditorStrings};
1
+ import{DEFAULT_PICK_WORDS as o}from"./chunk-ZAOM6PFH.js";import{DEFAULT_STYLE_CLIPBOARD_WORDS as r}from"./chunk-6WY6ZXJG.js";import{DEFAULT_CANVAS_WORDS as t}from"./chunk-GGTPNGFJ.js";import{DEFAULT_FIELDS_WORDS as m}from"./chunk-SUO5627P.js";import{DEFAULT_TREE_WORDS as n}from"./chunk-H4B72XCJ.js";import{DEFAULT_PANEL_WORDS as c}from"./chunk-7A7O2JWQ.js";import{DEFAULT_NODE_MENU_WORDS as f}from"./chunk-WK3AFPXY.js";import{DEFAULT_SAVE_WORDS as p}from"./chunk-H6DDIBQ4.js";import{DEFAULT_CHROME_WORDS as s,DEFAULT_NOTICE_WORDS as i}from"./chunk-KDIVA6WD.js";import{DEFAULT_LOCK_WORDS as u}from"./chunk-RE4LP46F.js";import{DEFAULT_RAIL_WORDS as e}from"./chunk-2OAZYSWJ.js";import{DEFAULT_COPY_WORDS as k}from"./chunk-ZT7M24XD.js";import{DEFAULT_DRAG_WORDS as j}from"./chunk-O2NLQBFX.js";var h={notice:i,lock:u,save:p,chrome:s,rail:e,tree:n,panel:c,fields:m,pick:o,drag:j,menu:f,styleClipboard:r,copy:k,canvas:t},l=o=>"object"==typeof o&&null!==o;function a(o,r){const t={};for(const m of Object.keys(o)){const n=o[m],c=r[m];null==c?t[m]=n:l(n)?t[m]=l(c)?a(n,c):n:t[m]=typeof c==typeof n?c:n}return t}function y(o,r){return r?a(o,r):o}export{h as DEFAULT_EDITOR_STRINGS,y as mergeEditorStrings};
@@ -1,4 +1,4 @@
1
- import{tokenizeInline as e,STANDARD_MARKUP as t}from"./chunk-6OPSJGAI.js";import{jsx as n,jsxs as l}from"react/jsx-runtime";import{useRef as r}from"react";function s(t,n){const l=[];let r=0;for(const s of e(t,n)){if("text"===s.kind){s.text.length>0&&(l.push({kind:"text",text:t.slice(r,r+s.text.length)}),r+=s.text.length);continue}const e=i(t,r,s.kind,s.text,n);if(!e)return[{kind:"text",text:t}];const o=r+e.open.length,c=o+s.text.length,a=c+e.close.length;l.push({kind:"delimiter",text:t.slice(r,o)}),l.push({kind:s.kind,text:t.slice(o,c)}),l.push({kind:"delimiter",text:t.slice(c,a)}),r=a}return l.map(e=>e.text).join("")!==t?[{kind:"text",text:t}]:l}function i(e,t,n,l,r){for(const s of r){if(s.kind!==n)continue;if(!e.startsWith(s.open,t))continue;const r=t+s.open.length;if(e.startsWith(l,r)&&e.startsWith(s.close,r+l.length))return s}return null}function o({value:e,rules:l=t,className:r,layerRef:i}){const o=s(e,l);/* @__PURE__ */
1
+ import{tokenizeInline as e,STANDARD_MARKUP as t}from"./chunk-SJQG5ENJ.js";import{jsx as n,jsxs as l}from"react/jsx-runtime";import{useRef as r}from"react";function s(t,n){const l=[];let r=0;for(const s of e(t,n)){if("text"===s.kind){s.text.length>0&&(l.push({kind:"text",text:t.slice(r,r+s.text.length)}),r+=s.text.length);continue}const e=i(t,r,s.kind,s.text,n);if(!e)return[{kind:"text",text:t}];const o=r+e.open.length,c=o+s.text.length,a=c+e.close.length;l.push({kind:"delimiter",text:t.slice(r,o)}),l.push({kind:s.kind,text:t.slice(o,c)}),l.push({kind:"delimiter",text:t.slice(c,a)}),r=a}return l.map(e=>e.text).join("")!==t?[{kind:"text",text:t}]:l}function i(e,t,n,l,r){for(const s of r){if(s.kind!==n)continue;if(!e.startsWith(s.open,t))continue;const r=t+s.open.length;if(e.startsWith(l,r)&&e.startsWith(s.close,r+l.length))return s}return null}function o({value:e,rules:l=t,className:r,layerRef:i}){const o=s(e,l);/* @__PURE__ */
2
2
  return n("div",{ref:i,className:["es-gold-layer",r??""].filter(Boolean).join(" "),"aria-hidden":"true",children:o.map((e,t)=>function(e,t){const{kind:l,text:r}=e;switch(l){case"delimiter":/* @__PURE__ */
3
3
  return n("span",{className:"es-gold-delim",children:r},t);case"accent":case"highlight":/* @__PURE__ */
4
4
  return n("em",{className:"es-gold-mark es-gold-accent",children:r},t);case"bold":/* @__PURE__ */
@@ -6,8 +6,8 @@ return n("strong",{className:"es-gold-mark es-gold-bold",children:r},t);case"ita
6
6
  return n("em",{className:"es-gold-mark es-gold-italic",children:r},t);case"strike":/* @__PURE__ */
7
7
  return n("s",{className:"es-gold-mark es-gold-strike",children:r},t);case"quiet":/* @__PURE__ */
8
8
  return n("span",{className:"es-gold-mark es-gold-quiet",children:r},t);default:/* @__PURE__ */
9
- return n("span",{className:"es-gold-text",children:r},t)}}(e,t))})}function c({value:e,onInput:s,onCommit:i,onCancel:c,multiline:a=!1,placeholder:u,className:d,rules:f=t,ariaLabel:m,disabled:h=!1,inputRef:g}){const p=r(null),k=r(e),x=r(!1);function v(e){x.current&&(x.current=!1,i?.(e))}/* @__PURE__ */
9
+ return n("span",{className:"es-gold-text",children:r},t)}}(e,t))})}function c({value:e,onInput:s,onCommit:i,onCancel:c,multiline:a=!1,placeholder:u,className:d,rules:f=t,ariaLabel:m,disabled:h=!1,inputRef:g}){const p=r(null),k=r(e),x=r(!1);function N(e){x.current&&(x.current=!1,i?.(e))}/* @__PURE__ */
10
10
  return l("div",{className:["es-gold",a?"es-gold-is-multiline":"es-gold-is-single",h?"es-gold-is-off":"",d??""].filter(Boolean).join(" "),children:[
11
11
  /* @__PURE__ */n(o,{value:e,rules:f,layerRef:p}),u&&""===e?
12
12
  /* @__PURE__ */n("div",{className:"es-gold-placeholder","aria-hidden":"true",children:u}):null,
13
- /* @__PURE__ */n("textarea",{ref:g,className:"es-gold-input",disabled:h,value:e,placeholder:u,"aria-label":m,onChange:function(e){x.current=!0,s(e.currentTarget.value)},onFocus:function(){k.current=e,x.current=!1},onBlur:function(){v(e)},onKeyDown:function(t){return"Escape"===t.key?(t.preventDefault(),x.current=!1,void c?.(k.current)):"Enter"!==t.key||a?void 0:(t.preventDefault(),void v(e))},onScroll:function(e){const t=p.current;t&&(t.scrollTop=e.currentTarget.scrollTop,t.scrollLeft=e.currentTarget.scrollLeft)}})]})}export{o as GoldLayer,c as GoldTextInput,s as goldSegments};
13
+ /* @__PURE__ */n("textarea",{ref:g,className:"es-gold-input",disabled:h,value:e,placeholder:u,"aria-label":m,onChange:function(e){x.current=!0,s(e.currentTarget.value)},onFocus:function(){k.current=e,x.current=!1},onBlur:function(){N(e)},onKeyDown:function(t){return"Escape"===t.key?(t.preventDefault(),x.current=!1,void c?.(k.current)):"Enter"!==t.key||a?void 0:(t.preventDefault(),void N(e))},onScroll:function(e){const t=p.current;t&&(t.scrollTop=e.currentTarget.scrollTop,t.scrollLeft=e.currentTarget.scrollLeft)}})]})}export{o as GoldLayer,c as GoldTextInput,s as goldSegments};
@@ -0,0 +1 @@
1
+ var e={bold:{open:"**",close:"**",placeholder:"bold text"},italic:{open:"_",close:"_",placeholder:"italic text"},strike:{open:"~~",close:"~~",placeholder:"struck out"},code:{open:"`",close:"`",placeholder:"code"},highlight:{open:"==",close:"==",placeholder:"highlighted text"},quiet:{open:"^^",close:"^^",placeholder:"quiet text"},underline:{open:"[",close:"]{underline}",placeholder:"underlined text"},sup:{open:"[",close:"]{sup}",placeholder:"superscript"},sub:{open:"[",close:"]{sub}",placeholder:"subscript"}};function t(e){return/^[a-z][a-z0-9-]*$/.test(e)}function n(e,t){const n=/^\{(underline|sup|sub|color=([a-z][a-z0-9-]*))\}/.exec(e.slice(t,t+64));return n?void 0===n[2]?{kind:n[1],length:n[0].length}:{kind:"color",color:n[2],length:n[0].length}:null}var l={bold:e.bold.placeholder,italic:e.italic.placeholder,strike:e.strike.placeholder,code:e.code.placeholder,highlight:e.highlight.placeholder,quiet:e.quiet.placeholder,link:"link text",underline:e.underline.placeholder,sup:e.sup.placeholder,sub:e.sub.placeholder,color:"colored text"},o={bullet:()=>"- ",number:e=>`${e+1}. `,quote:()=>"> "};function r(t,n,r,i,c=p,u=l){if("clear"===i)return M(t,n,r,c);const a=t.slice(n,r);if("link"===i){const e=a||u.link,l=`[${e}](https://)`;return{text:t.slice(0,n)+l+t.slice(r),selectionStart:n+e.length+3,selectionEnd:n+l.length-1}}const d=o[i];if(d){const e=t.lastIndexOf("\n",Math.max(n-1,0))+1,l=t.indexOf("\n",r),o=-1===l?t.length:l,i=t.slice(e,o).split("\n"),s=i.every((e,t)=>e.startsWith(d(t))),c=i.map((e,t)=>s?e.slice(d(t).length):d(t)+e).join("\n");return{text:t.slice(0,e)+c+t.slice(o),selectionStart:e,selectionEnd:e+c.length}}const{open:h,close:f}=e[i],k=i,g=u[k]??l[k];if(s(t,n,r,i))return{text:t.slice(0,n-h.length)+a+t.slice(r+f.length),selectionStart:n-h.length,selectionEnd:n-h.length+a.length};const m=a||g;return{text:t.slice(0,n)+h+m+f+t.slice(r),selectionStart:n+h.length,selectionEnd:n+h.length+m.length}}function i(e,o,r,i,s=l){const c={text:e,selectionStart:o,selectionEnd:r};if(null!==i&&!t(i))return c;const u=e.slice(o,r),a=o>=1&&"["===e[o-1]&&"]"===e[r]?n(e,r+1):null;if("color"===a?.kind){const t=o-1,n=e.slice(r+1+a.length);return null===i?{text:e.slice(0,t)+u+n,selectionStart:t,selectionEnd:t+u.length}:{text:`${e.slice(0,r)}]{color=${i}}${n}`,selectionStart:o,selectionEnd:r}}if(null===i)return c;const d=u||(s.color??l.color);return{text:`${e.slice(0,o)}[${d}]{color=${i}}${e.slice(r)}`,selectionStart:o+1,selectionEnd:o+1+d.length}}function s(t,n,l,o){const r=e[o];if(!r)return!1;const{open:i,close:s}=r;return n>=i.length&&t.slice(n-i.length,n)===i&&t.slice(l,l+s.length)===s}function c(e,t,n){const l=0===t?0:e.lastIndexOf("\n",t-1)+1;for(let o=e.lastIndexOf("[",t);o>=l;o=0===o?-1:e.lastIndexOf("[",o-1)){const t=$(e,o);if(t&&n<=t.end)return{start:o,end:t.end,label:t.label,href:t.href}}return null}function u(e,t,n,l){const o=c(e,t,n),r=o?o.start:t,i=o?o.end:n,s=`[${o?o.label:e.slice(t,n)||l}](${l})`,u=r+s.length;return{text:e.slice(0,r)+s+e.slice(i),selectionStart:u,selectionEnd:u}}function a(e,t){return{text:e.slice(0,t.start)+t.label+e.slice(t.end),selectionStart:t.start,selectionEnd:t.start+t.label.length}}var d=[{style:"bold",label:"B",name:"Strong",title:"Strong · **words** · ⌘B",shortcut:"b"},{style:"italic",label:"I",name:"Italic",title:"Italic · _words_ · ⌘I",shortcut:"i"},{style:"strike",label:"S",name:"Strikethrough",title:"Strikethrough · ~~words~~"},{style:"highlight",label:"◆",name:"Emphasis",title:"Emphasis · ==words=="},{style:"quiet",label:"a",name:"Quiet",title:"Quiet · ^^words^^"},{style:"code",label:"‹›",name:"Code",title:"Code"},{style:"link",label:"🔗",name:"Link",title:"Link · [words](https://…) · ⌘K",shortcut:"k"},{style:"bullet",label:"•",name:"Bulleted list",title:"Bulleted list"},{style:"number",label:"1.",name:"Numbered list",title:"Numbered list"},{style:"quote",label:"❝",name:"Quote",title:"Quote"},{style:"clear",label:"T×",name:"Clear marks",title:"Clear marks · ⌘⇧X",shortcut:"shift+x"}],h={bold:"Strong",highlight:"Emphasis",quiet:"Quiet"};function f(e){return d.filter(t=>e.includes(t.style))}var p=[{open:"**",close:"**",kind:"bold"},{open:"==",close:"==",kind:"highlight"},{open:"~~",close:"~~",kind:"strike"},{open:"_",close:"_",kind:"italic",wordBoundary:!0},{open:"^^",close:"^^",kind:"quiet"},{open:"@@",close:"@@",kind:"highlight"},{open:"++",close:"++",kind:"bold"}],k=d.map(e=>e.style).filter(e=>p.some(t=>t.kind===e)),g=[...p,{open:"*",close:"*",kind:"accent"}],m=[...p,{open:"*",close:"*",kind:"accent"},{open:"#",close:"#",kind:"bold",notBefore:"0123456789"},{open:"[",close:"]",kind:"italic",notBefore:"(",notBeforeBlock:!0}];function b(e){return!/\s/.test(e)&&!/[!-\/:-@[-`{-~]/.test(e)}function x(e,t){const n=[];let l="",o=0;for(;o<e.length;){const r=S(e,o,t);r?(n.push({kind:"text",text:l}),l="",n.push({kind:r.rule.kind,text:r.inner}),o=r.end):(l+=e[o],o+=1)}return n.push({kind:"text",text:l}),n}function S(e,t,l){for(const o of l){if(!e.startsWith(o.open,t))continue;if(o.wordBoundary&&t>0&&b(e[t-1]))continue;const l=t+o.open.length,r=e.indexOf(o.close,l);if(r<l+1)continue;const i=e.slice(l,r);if(i.includes(o.close[0]))continue;if(i.includes("\n"))continue;const s=r+o.close.length,c=e[s];if((!o.notBefore||void 0===c||!o.notBefore.includes(c))&&!(o.notBeforeBlock&&n(e,s)||o.wordBoundary&&void 0!==c&&b(c)))return{rule:o,inner:i,end:s}}return null}function y(e,t){return x(e,t).map(e=>e.text).join("")}var v=["http","https","mailto","tel"];function E(e){if(""===e||/[\s\u0000-\u001f\u007f]/.test(e))return!1;const t=/^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(e);return!t||v.includes(t[1].toLowerCase())}function $(e,t){if("["!==e[t])return null;const n=e.indexOf("]",t+1);if(n<t+2||"("!==e[n+1])return null;const l=e.slice(t+1,n);if(l.includes("["))return null;const o=e.indexOf(")",n+2);if(-1===o)return null;const r=e.slice(n+2,o);return E(r)?{label:l,href:r,end:o+1}:null}function B(e,t){if("["!==e[t])return null;let l=0;for(let o=t;o<e.length;o+=1){const r=e[o];if("\n"===r)return null;if("["===r)l+=1;else if("]"===r){if(l-=1,l>0)continue;if(o===t+1)return null;const r=n(e,o+1);return r?{kind:r.kind,color:r.color,label:e.slice(t+1,o),close:e.slice(o,o+1+r.length),end:o+1+r.length}:null}}return null}var w=4;function q(e,t,n){const l=[];let o="";const r=()=>{o&&l.push({kind:"text",text:o}),o=""},i=e=>n+1<w?q(e,t,n+1):[{kind:"text",text:e}];let s=0;for(;s<e.length;){const n=$(e,s);if(n){r(),l.push({kind:"link",href:n.href,children:i(n.label)}),s=n.end;continue}const c=B(e,s);if(c){r(),l.push({kind:c.kind,open:"[",close:c.close,...void 0===c.color?{}:{color:c.color},children:i(c.label)}),s=c.end;continue}const u=S(e,s,t);u?(r(),l.push({kind:u.rule.kind,open:u.rule.open,close:u.rule.close,children:i(u.inner)}),s=u.end):(o+=e[s],s+=1)}return r(),l}function O(e,t){return e.split("\n").map(e=>{const{bullet:n,number:l,rest:o}=function(e){if(e.startsWith("- ")&&""!==e.slice(2).trim())return{bullet:!0,number:null,rest:e.slice(2)};const t=/^([0-9]{1,3})\. /.exec(e);return t&&""!==e.slice(t[0].length).trim()?{bullet:!1,number:t[1],rest:e.slice(t[0].length)}:{bullet:!1,number:null,rest:e}}(e);return{bullet:n,number:l,children:q(o,t,0)}})}function I(e){return null!=e.number?`${e.number}. `:e.bullet?"- ":""}function z(e){return e.map(e=>"text"===e.kind?e.text:"link"===e.kind?`[${z(e.children)}](${e.href})`:e.open+z(e.children)+e.close).join("")}function _(e){return e.map(e=>I(e)+z(e.children)).join("\n")}function C(n,l,o){if("link"===l)return void 0===o?null:{id:n,kind:"link",open:"[",close:`](${o})`,href:o};if("color"===l)return void 0!==o&&t(o)?{id:n,kind:"color",open:"[",close:`]{color=${o}}`,color:o}:null;const r=e[l];return r&&"code"!==l?{id:n,kind:l,open:r.open,close:r.close}:null}function Q(e,t){let n=0,l=0;return e.split("\n").map(e=>{const[o]=O(e,t);let r=l+I(o).length;l+=e.length+1;const i=[],s=(e,t)=>{for(const l of e){if("text"===l.kind){for(const e of l.text)i.push({ch:e,marks:t,at:r}),r+=e.length;continue}const e="link"===l.kind?C(++n,"link",l.href):{id:++n,kind:l.kind,open:l.open,close:l.close,...void 0===l.color?{}:{color:l.color}};r+=e.open.length,s(l.children,[...t,e]),r+=e.close.length}};return s(o.children,[]),{bullet:o.bullet,number:o.number??null,chars:i}})}function j(e){let t="";const n=[];return e.forEach((e,l)=>{l>0&&(t+="\n"),t+=I(e);const o=[],r=[];for(const n of e.chars){let e=0;for(;e<o.length&&e<n.marks.length&&o[e].id===n.marks[e].id;)e+=1;for(;o.length>e;)t+=o.pop().close;for(let l=e;l<n.marks.length;l+=1)t+=n.marks[l].open,o.push(n.marks[l]);r.push(t.length),t+=n.ch}for(;o.length>0;)t+=o.pop().close;n.push(r)}),{text:t,at:n}}function L(e,t){return e.length===t.length&&e.every((e,n)=>{const l=t[n];return e.bullet===l.bullet&&(e.number??null)===(l.number??null)&&(e.chars.length===l.chars.length&&e.chars.every((e,t)=>{const n=l.chars[t];return e.ch===n.ch&&e.marks.length===n.marks.length&&e.marks.every((e,t)=>e.kind===n.marks[t].kind&&e.href===n.marks[t].href&&e.color===n.marks[t].color)}))})}function M(e,t,n,l=p){const o=Q(e,l),r=o.flatMap(e=>e.chars),i={text:e,selectionStart:t,selectionEnd:n},s=e=>o.map(t=>({bullet:t.bullet,number:t.number,chars:t.chars.map(t=>({...t,marks:t.marks.filter(n=>"link"===n.kind||!e(t,n))}))})),c=e=>{const t=j(e);return L(e,Q(t.text,l))?t:null},u=(e,t)=>{let n=r.indexOf(t);for(let t=0;t<e.at.length;t+=1){if(n<e.at[t].length)return e.at[t][n];n-=e.at[t].length}return 0};if(t===n){const e=[...r].reverse().find(e=>e.at<t),n=r.find(e=>e.at>=t),l=new Set([...e?.marks??[],...n?.marks??[]].map(e=>e.id));if(![...l].some(e=>r.some(t=>t.marks.some(t=>t.id===e&&"link"!==t.kind))))return i;const o=c(s((e,t)=>l.has(t.id)));if(!o)return i;const a=n?u(o,n):e?u(o,e)+e.ch.length:0;return{text:o.text,selectionStart:a,selectionEnd:a}}const a=new Set(r.filter(e=>e.at>=t&&e.at<n));if(0===a.size)return i;const d=new Set([...a].flatMap(e=>e.marks.map(e=>e.id))),h=c(s(e=>a.has(e)))??c(s((e,t)=>d.has(t.id)));if(!h)return i;const f=r.find(e=>a.has(e)),k=[...r].reverse().find(e=>a.has(e));return{text:h.text,selectionStart:u(h,f),selectionEnd:u(h,k)+k.ch.length}}export{m as CAMPAIGN_MARKUP,k as COPY_FIELD_TOOLS,d as MARKUP_TOOLS,h as MARK_NAMES,l as MARK_PLACEHOLDERS,p as STANDARD_MARKUP,g as STOREFRONT_MARKUP,i as applyColor,r as applyMark,M as clearMarks,c as findLink,t as isColorName,E as isSafeLinkHref,s as markedAt,Q as markedLines,f as markupTools,O as parseMarkup,a as removeLink,L as sameMarks,_ as serializeMarkup,C as spanFor,y as stripInline,x as tokenizeInline,u as writeLink,j as writeMarkedLines};
@@ -1 +1 @@
1
- import{MARKUP_TOOLS as e,MARK_PLACEHOLDERS as t}from"./chunk-6OPSJGAI.js";var i={formatting:"Formatting",alignment:"Alignment",align:{left:"Left",center:"Center",right:"Right",justify:"Justify"},link:{title:"Link",label:"Link to",placeholder:"https://… or /page",refused:"Use a web address (https://…), a page on this site (/…), mailto: or tel:.",remove:"Remove link",apply:"Apply"},marks:Object.fromEntries(e.map(e=>[e.style,{name:e.name??e.title,title:e.title}])),placeholders:t};export{i as DEFAULT_COPY_WORDS};
1
+ import{MARKUP_TOOLS as e,MARK_PLACEHOLDERS as t}from"./chunk-SJQG5ENJ.js";var i={formatting:"Formatting",alignment:"Alignment",align:{left:"Left",center:"Center",right:"Right",justify:"Justify"},link:{title:"Link",label:"Link to",placeholder:"https://… or /page",refused:"Use a web address (https://…), a page on this site (/…), mailto: or tel:.",remove:"Remove link",apply:"Apply"},marks:Object.fromEntries(e.map(e=>[e.style,{name:e.name??e.title,title:e.title}])),placeholders:t};export{i as DEFAULT_COPY_WORDS};
@@ -1,10 +1,10 @@
1
- import{DEFAULT_COPY_WORDS as e}from"../chunk-2LUSK32B.js";import{SettingsSegmented as t}from"../chunk-QB3BZIRA.js";import{GoldTextInput as n}from"../chunk-CERTFXCV.js";import{applyMark as l,STANDARD_MARKUP as r,writeMarkedLines as o,sameMarks as i,markedLines as a,spanFor as s,markupTools as c,findLink as u,markedAt as d,removeLink as p,writeLink as h,isSafeLinkHref as f}from"../chunk-6OPSJGAI.js";import{useWords as m}from"../chunk-MFIRYGHW.js";import"../chunk-BZ5ASXOL.js";import{AlignSeparateIcon as y,AlignRightIcon as b,AlignCenterIcon as g,AlignLeftIcon as k,ClearMarksIcon as v,LinkIcon as x,QuietIcon as C,EmphasisIcon as w,StrikeIcon as S,ItalicIcon as D,BoldIcon as N}from"../chunk-PI26YXYD.js";import{useRef as j,useLayoutEffect as E,useState as L,useEffect as P,useId as K}from"react";import{jsx as T,jsxs as z,Fragment as A}from"react/jsx-runtime";var B=["left","center","right","justify"],R=e.align,$={left:/* @__PURE__ */T(k,{}),center:/* @__PURE__ */T(g,{}),right:/* @__PURE__ */T(b,{}),justify:/* @__PURE__ */T(y,{})},M={three:{labelsPx:94.5,widestLabelPx:39.94},four:{labelsPx:140,widestLabelPx:44}};function F(e,t=R){return B.filter(t=>e.includes(t)).map(e=>({id:e,label:t[e],icon:$[e],title:t[e]}))}var I=/[\u1100-\u11ff\u2e80-\u9fff\uac00-\ud7af\uf900-\ufaff\uff00-\uffef]/;function Y(e){if(e.every(e=>e.label===R[e.id]))return e.length>3?M.four:M.three;const t=e.map(e=>[...e.label].reduce((e,t)=>e+(I.test(t)?13:8),0));return{labelsPx:t.reduce((e,t)=>e+t,0),widestLabelPx:Math.max(0,...t)}}function q(e,t){const n=t?.selectionStart??e.length;return{start:n,end:t?.selectionEnd??n}}function O(e,t,n,r=l){const{start:o,end:i}=q(e,n);return r(e,o,i,t)}function U(e,t,n){const{start:l,end:r}=q(e,n),o=l+t.length;return{text:e.slice(0,l)+t+e.slice(r),selectionStart:o,selectionEnd:o}}var X=1e3;function Z(e=200){let t=[],n=[],l=null,r=0;return{record(o,i,a){const s="type"===i&&"type"===l&&a-r<1e3;l=i,r=a,n=[],s||(t.push(o),t.length>e&&t.shift())},undo(e){const r=t.pop();return r?(n.push(e),l=null,r):null},redo(e){const r=n.pop();return r?(t.push(e),l=null,r):null},reset(){t=[],n=[],l=null}}}function G({href:t,editing:n,onApply:l,onRemove:r,onClose:o}){const i=m("copy",e).link,a=K(),[s,c]=L(t),[u,d]=L(!1),p=j(null);P(()=>{p.current?.focus(),p.current?.select()},[]);const h=()=>{const e=s.trim();f(e)?l(e):d(!0)};/* @__PURE__ */
1
+ import{DEFAULT_COPY_WORDS as e}from"../chunk-ZT7M24XD.js";import{SettingsSegmented as t}from"../chunk-QB3BZIRA.js";import{GoldTextInput as n}from"../chunk-JYPOOHII.js";import{applyMark as l,STANDARD_MARKUP as r,writeMarkedLines as o,sameMarks as i,markedLines as a,spanFor as s,markupTools as c,findLink as u,markedAt as d,removeLink as p,writeLink as h,isSafeLinkHref as f}from"../chunk-SJQG5ENJ.js";import{useWords as m}from"../chunk-MFIRYGHW.js";import"../chunk-BZ5ASXOL.js";import{AlignSeparateIcon as y,AlignRightIcon as b,AlignCenterIcon as g,AlignLeftIcon as k,ClearMarksIcon as v,LinkIcon as x,QuietIcon as w,EmphasisIcon as C,StrikeIcon as D,ItalicIcon as N,BoldIcon as S}from"../chunk-PI26YXYD.js";import{useRef as j,useLayoutEffect as E,useState as L,useEffect as P,useId as K}from"react";import{jsx as T,jsxs as z,Fragment as $}from"react/jsx-runtime";var A=["left","center","right","justify"],B=e.align,M={left:/* @__PURE__ */T(k,{}),center:/* @__PURE__ */T(g,{}),right:/* @__PURE__ */T(b,{}),justify:/* @__PURE__ */T(y,{})},R={three:{labelsPx:94.5,widestLabelPx:39.94},four:{labelsPx:140,widestLabelPx:44}};function I(e,t=B){return A.filter(t=>e.includes(t)).map(e=>({id:e,label:t[e],icon:M[e],title:t[e]}))}var Y=/[\u1100-\u11ff\u2e80-\u9fff\uac00-\ud7af\uf900-\ufaff\uff00-\uffef]/;function F(e){if(e.every(e=>e.label===B[e.id]))return e.length>3?R.four:R.three;const t=e.map(e=>[...e.label].reduce((e,t)=>e+(Y.test(t)?13:8),0));return{labelsPx:t.reduce((e,t)=>e+t,0),widestLabelPx:Math.max(0,...t)}}function O(e,t){const n=t?.selectionStart??e.length;return{start:n,end:t?.selectionEnd??n}}function Z(e,t,n,r=l){const{start:o,end:i}=O(e,n);return r(e,o,i,t)}function q(e,t,n){const{start:l,end:r}=O(e,n),o=l+t.length;return{text:e.slice(0,l)+t+e.slice(r),selectionStart:o,selectionEnd:o}}var H=1e3;function J(e=200){let t=[],n=[],l=null,r=0;return{record(o,i,a){const s="type"===i&&"type"===l&&a-r<1e3;l=i,r=a,n=[],s||(t.push(o),t.length>e&&t.shift())},undo(e){const r=t.pop();return r?(n.push(e),l=null,r):null},redo(e){const r=n.pop();return r?(t.push(e),l=null,r):null},reset(){t=[],n=[],l=null}}}function X({href:t,editing:n,onApply:l,onRemove:r,onClose:o}){const i=m("copy",e).link,a=K(),[s,c]=L(t),[u,d]=L(!1),p=j(null);P(()=>{p.current?.focus(),p.current?.select()},[]);const h=()=>{const e=s.trim();f(e)?l(e):d(!0)};/* @__PURE__ */
2
2
  return z("div",{role:"dialog","aria-label":i.title,className:"es-copy-link",onKeyDown:e=>{"Enter"===e.key?(e.preventDefault(),h()):"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),o())},children:[
3
3
  /* @__PURE__ */T("label",{htmlFor:a,className:"es-copy-link-label",children:i.label}),
4
4
  /* @__PURE__ */T("input",{ref:p,id:a,type:"text",className:"es-copy-link-input",value:s,placeholder:i.placeholder,spellCheck:!1,autoComplete:"off","aria-invalid":u||void 0,"aria-describedby":u?`${a}-why`:void 0,onChange:e=>{c(e.target.value),d(!1)}}),u?/* @__PURE__ */T("p",{id:`${a}-why`,role:"alert",className:"es-copy-link-why",children:i.refused}):null,
5
5
  /* @__PURE__ */z("div",{className:"es-copy-link-actions",children:[n?/* @__PURE__ */T("button",{type:"button",className:"es-copy-link-btn",onClick:r,children:i.remove}):null,
6
- /* @__PURE__ */T("button",{type:"button",className:"es-copy-link-btn is-primary",onClick:h,disabled:""===s.trim(),children:i.apply})]})]})}var H=/* @__PURE__ */new Set(["script","style","head","title","meta","link","template","noscript","svg","math","object","iframe"]),W=/* @__PURE__ */new Set(["p","div","li","ul","ol","dl","dt","dd","h1","h2","h3","h4","h5","h6","blockquote","pre","table","thead","tbody","tfoot","tr","section","article","header","footer","aside","nav","figure","figcaption","address","hr"]);function J(e,t){const n=t.rules??r,l=e.html&&""!==e.html.trim()?function(e,t,n){const l=t.createElement("template");l.innerHTML=e;const r=[[]],s=()=>r[r.length-1],c=()=>{const e=s();for(;e.length>0&&" "===e[e.length-1].ch;)e.pop();e.length>0&&r.push([])},u=(e,t,n,l)=>{if(3===e.nodeType){for(const r of e.textContent??""){const e=/\s/.test(r)?" ":r,o=s();(" "!==e||0!==o.length&&" "!==o[o.length-1].ch)&&o.push({ch:e,bold:t,italic:n,href:l})}return}if(1!==e.nodeType&&11!==e.nodeType)return;const o=e,i=1===e.nodeType?o.localName:"";if(H.has(i))return;if("br"===i)return void r.push([]);let a=t,d=n,p=l;if("b"!==i&&"strong"!==i||(a=!0),"i"!==i&&"em"!==i||(d=!0),"a"===i){const e=(o.getAttribute("href")??"").trim();p=f(e)?e:null}const h=1===e.nodeType?o.style:null;if(h){const e=h.fontWeight;"bold"===e||"bolder"===e||Number(e)>=600?a=!0:("normal"===e||"lighter"===e||""!==e&&Number(e)<600)&&(a=!1),"italic"===h.fontStyle||"oblique"===h.fontStyle?d=!0:"normal"===h.fontStyle&&(d=!1)}const m=W.has(i);m&&c();for(const t of[...e.childNodes])u(t,a,d,p);m&&c()};u(l.content,!1,!1,null);for(;r.length>1&&0===r[r.length-1].length;)r.pop();return r.map(e=>function(e,t){const n=t=>e.map((n,l)=>n[t]&&(" "!==n.ch||Boolean(e[l-1]?.[t])&&Boolean(e[l+1]?.[t]))),l=[{bold:!0,italic:!0,links:!0},{bold:!0,italic:!1,links:!0},{bold:!1,italic:!1,links:!0},{bold:!1,italic:!1,links:!1}];for(const r of l){const l=Q(e,r.bold?n("bold"):null,r.italic?n("italic"):null,r.links),s=o([l]).text;if(i([l],a(s,t)))return s}return e.map(e=>e.ch).join("")}(e,n))}(e.html,t.doc,n):(e.text??"").replace(/\r\n?/g,"\n").split("\n");return t.multiline?l.join("\n"):l.map(e=>e.trim()).filter(e=>""!==e).join(" ")}function Q(e,t,n,l){let r=0,o=null,i=null,a=null;return{bullet:!1,chars:e.map((e,c)=>{const u=l?e.href:null;return o=null===u?null:o&&o.href===u?o:s(++r,"link",u),i=t?.[c]?i??s(++r,"bold"):null,a=n?.[c]?a??s(++r,"italic"):null,{ch:e.ch,at:-1,marks:[o,i,a].filter(e=>null!==e)}})}}var V={bold:/* @__PURE__ */T(N,{size:16}),italic:/* @__PURE__ */T(D,{size:16}),strike:/* @__PURE__ */T(S,{size:16}),highlight:/* @__PURE__ */T(w,{size:16}),quiet:/* @__PURE__ */T(C,{size:16}),link:/* @__PURE__ */T(x,{size:16}),clear:/* @__PURE__ */T(v,{size:16})};function _(e){if(!e)return;const t=e.split("+"),n=t.pop().toUpperCase();return["Meta",...t.map(e=>e[0].toUpperCase()+e.slice(1)),n].join("+")}var ee={bold:"is-bold",italic:"is-italic",strike:"is-strike"};function te({tools:t,onApply:n,disabled:l=!1,actions:r,align:o,glyphs:i,ariaLabel:a,pressed:s,open:u=null}){const d=m("copy",e),p="string"==typeof t[0]?c(t).map(e=>({...e,...d.marks[e.style]})):t;return 0!==p.length||r||o?/* @__PURE__ */z("div",{className:"es-copy-bar",role:"group","aria-label":a??d.formatting,children:[p.map(e=>{const t=i?.[e.style]??V[e.style],r=u===e.style||Boolean(s?.[e.style]);/* @__PURE__ */
7
- return T("button",{type:"button",onMouseDown:e=>e.preventDefault(),onClick:()=>n(e.style),disabled:l,title:e.title,"aria-label":e.name??e.title,"aria-keyshortcuts":_(e.shortcut),"aria-pressed":s||u?r:void 0,"aria-haspopup":"link"===e.style&&s?"dialog":void 0,"aria-expanded":"link"===e.style&&s?"link"===u:void 0,className:`es-copy-mark${t?" has-glyph":ee[e.style]?` ${ee[e.style]}`:""}${r?" is-active":""}`,children:t??e.label},e.style)}),r?/* @__PURE__ */z(A,{children:[
8
- /* @__PURE__ */T("span",{className:"es-copy-bar-split","aria-hidden":"true"}),r]}):null,o?/* @__PURE__ */T("span",{className:"es-copy-bar-end",children:o}):null]}):null}function ne({target:e,onChange:t}){const n=j(null);return E(()=>{const t=n.current,l=e.current;t&&l&&l.value===t.text&&(n.current=null,l.focus(),l.setSelectionRange(t.start,t.end))}),l=>{const r=l(e.current);t(r.text),n.current={start:r.selectionStart,end:r.selectionEnd,text:r.text}}}function le({value:o,onChange:i,onCommit:a,onCancel:s,multiline:f=!1,placeholder:y,ariaLabel:b,className:g,readOnly:k=!1,rules:v,tools:x=[],writeMark:C,actions:w,align:S,glyphs:D,barLabel:N,renderFooter:E,inputRef:K,barShows:A="always"}){const B=m("copy",e),R=j(null),$=K??R,[M,I]=L(!1),[q,X]=L(null),H=j(Z()).current,W=j(null);P(()=>{const e=W.current;e&&o===e.to?W.current=null:e&&o===e.from||(W.current=null,H.reset())},[o,H]);const Q=e=>{W.current={from:W.current?.from??o,to:e},i(e)},V=e=>({text:o,start:e?.selectionStart??q?.start??o.length,end:e?.selectionEnd??q?.end??o.length}),_=ne({target:$,onChange:Q}),ee=e=>(X({start:e.selectionStart,end:e.selectionEnd}),e),le=e=>_(t=>(H.record(V(t),"edit",Date.now()),ee(e(t)))),[re,oe]=L(null),ie=v??r,ae="string"==typeof x[0]?c(x):x,se=ae.map(e=>e.style),ce={};if(q)for(const e of se)ce[e]="link"===e?null!==u(o,q.start,q.end):d(o,q.start,q.end,e);const ue=e=>{if("clear"===e)return void le(t=>O(o,e,t,(e,t,n)=>l(e,t,n,"clear",ie)));if("link"!==e){const t=C??((e,t,n,o)=>l(e,t,n,o,r,B.placeholders));return void le(n=>O(o,e,n,t))}const t=$.current,n=t?.selectionStart??o.length,i=t?.selectionEnd??n;oe({start:n,end:i,link:u(o,n,i)})},de=S?F(S.allow,B.align):[];/* @__PURE__ */
9
- return z("div",{className:"es-copy"+(g?` ${g}`:""),onFocus:()=>I(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||I(!1)},onKeyDown:e=>{if(k||e.target!==$.current)return;if(e.altKey||e.metaKey===e.ctrlKey)return;const t=e.key.toLowerCase(),n="KeyZ"===e.code||"z"===t,l=("KeyY"===e.code||"y"===t)&&!e.shiftKey;if(n||l)return e.preventDefault(),e.stopPropagation(),r=l||e.shiftKey?"redo":"undo",void _(e=>{const t=V(e),n=H[r](t);return ee(n?{text:n.text,selectionStart:n.start,selectionEnd:n.end}:{text:t.text,selectionStart:t.start,selectionEnd:t.end})});var r;const o=`${e.shiftKey?"shift+":""}${t}`,i=ae.find(e=>e.shortcut===o);i&&(e.preventDefault(),e.stopPropagation(),ue(i.style))},onPaste:e=>{const t=$.current;if(k||!t||e.target!==t)return;e.preventDefault();const n=J({html:e.clipboardData.getData("text/html"),text:e.clipboardData.getData("text/plain")},{doc:t.ownerDocument,multiline:f,rules:ie});le(e=>U(o,n,e))},onSelect:()=>{const e=$.current;e&&e.ownerDocument.activeElement===e&&X({start:e.selectionStart??o.length,end:e.selectionEnd??o.length})},children:["always"===A||M||null!==re?/* @__PURE__ */T(te,{tools:x,disabled:k,actions:w,glyphs:D,ariaLabel:N,pressed:ce,open:re?"link":null,onApply:ue,align:S?/* @__PURE__ */T(t,{options:de,value:S.value,onChange:S.onChange,ariaLabel:B.alignment,disabled:k||S.disabled,fit:Y(de)}):null}):null,
10
- /* @__PURE__ */T(n,{value:o,onInput:e=>{H.record(V(null),"type",Date.now()),Q(e)},onCommit:a,onCancel:s,multiline:f,placeholder:y,ariaLabel:b,rules:v,disabled:k,inputRef:$,className:"es-copy-box"}),re?/* @__PURE__ */T(G,{href:re.link?.href??"",editing:null!==re.link,onApply:e=>{const t=re;oe(null),le(()=>h(o,t.start,t.end,e))},onRemove:()=>{const e=re.link;oe(null),e&&le(()=>p(o,e))},onClose:()=>{oe(null),$.current?.focus()}}):null,E?E({focused:M,insert:e=>le(t=>U(o,e,t))}):null]})}export{B as COPY_ALIGNS,M as COPY_ALIGN_FIT,$ as COPY_ALIGN_GLYPHS,R as COPY_ALIGN_LABELS,le as CopyBox,te as MarkBar,X as TYPING_BURST_MS,_ as ariaShortcut,F as copyAlignOptions,Z as createHistory,U as insertSelection,O as markSelection,J as pasteToMarkup,ne as useCaretEdit};
6
+ /* @__PURE__ */T("button",{type:"button",className:"es-copy-link-btn is-primary",onClick:h,disabled:""===s.trim(),children:i.apply})]})]})}var G=/* @__PURE__ */new Set(["script","style","head","title","meta","link","template","noscript","svg","math","object","iframe"]),Q=/* @__PURE__ */new Set(["p","div","li","ul","ol","dl","dt","dd","h1","h2","h3","h4","h5","h6","blockquote","pre","table","thead","tbody","tfoot","tr","section","article","header","footer","aside","nav","figure","figcaption","address","hr"]);function U(e,t){const n=t.rules??r,l=e.html&&""!==e.html.trim()?function(e,t,n){const l=t.createElement("template");l.innerHTML=e;const r=[[]],s=()=>r[r.length-1],c=()=>{const e=s();for(;e.length>0&&" "===e[e.length-1].ch;)e.pop();e.length>0&&r.push([])},u=(e,t,n,l)=>{if(3===e.nodeType){for(const r of e.textContent??""){const e=/\s/.test(r)?" ":r,o=s();(" "!==e||0!==o.length&&" "!==o[o.length-1].ch)&&o.push({ch:e,bold:t,italic:n,href:l})}return}if(1!==e.nodeType&&11!==e.nodeType)return;const o=e,i=1===e.nodeType?o.localName:"";if(G.has(i))return;if("br"===i)return void r.push([]);let a=t,d=n,p=l;if("b"!==i&&"strong"!==i||(a=!0),"i"!==i&&"em"!==i||(d=!0),"a"===i){const e=(o.getAttribute("href")??"").trim();p=f(e)?e:null}const h=1===e.nodeType?o.style:null;if(h){const e=h.fontWeight;"bold"===e||"bolder"===e||Number(e)>=600?a=!0:("normal"===e||"lighter"===e||""!==e&&Number(e)<600)&&(a=!1),"italic"===h.fontStyle||"oblique"===h.fontStyle?d=!0:"normal"===h.fontStyle&&(d=!1)}const m=Q.has(i);m&&c();for(const t of[...e.childNodes])u(t,a,d,p);m&&c()};u(l.content,!1,!1,null);for(;r.length>1&&0===r[r.length-1].length;)r.pop();return r.map(e=>function(e,t){const n=t=>e.map((n,l)=>n[t]&&(" "!==n.ch||Boolean(e[l-1]?.[t])&&Boolean(e[l+1]?.[t]))),l=[{bold:!0,italic:!0,links:!0},{bold:!0,italic:!1,links:!0},{bold:!1,italic:!1,links:!0},{bold:!1,italic:!1,links:!1}];for(const r of l){const l=W(e,r.bold?n("bold"):null,r.italic?n("italic"):null,r.links),s=o([l]).text;if(i([l],a(s,t)))return s}return e.map(e=>e.ch).join("")}(e,n))}(e.html,t.doc,n):(e.text??"").replace(/\r\n?/g,"\n").split("\n");return t.multiline?l.join("\n"):l.map(e=>e.trim()).filter(e=>""!==e).join(" ")}function W(e,t,n,l){let r=0,o=null,i=null,a=null;return{bullet:!1,chars:e.map((e,c)=>{const u=l?e.href:null;return o=null===u?null:o&&o.href===u?o:s(++r,"link",u),i=t?.[c]?i??s(++r,"bold"):null,a=n?.[c]?a??s(++r,"italic"):null,{ch:e.ch,at:-1,marks:[o,i,a].filter(e=>null!==e)}})}}var V={bold:/* @__PURE__ */T(S,{size:16}),italic:/* @__PURE__ */T(N,{size:16}),strike:/* @__PURE__ */T(D,{size:16}),highlight:/* @__PURE__ */T(C,{size:16}),quiet:/* @__PURE__ */T(w,{size:16}),link:/* @__PURE__ */T(x,{size:16}),clear:/* @__PURE__ */T(v,{size:16})};function _(e){if(!e)return;const t=e.split("+"),n=t.pop().toUpperCase();return["Meta",...t.map(e=>e[0].toUpperCase()+e.slice(1)),n].join("+")}var ee={bold:"is-bold",italic:"is-italic",strike:"is-strike"};function te({tools:t,onApply:n,disabled:l=!1,actions:r,align:o,glyphs:i,ariaLabel:a,pressed:s,open:u=null}){const d=m("copy",e),p="string"==typeof t[0]?c(t).map(e=>({...e,...d.marks[e.style]})):t;return 0!==p.length||r||o?/* @__PURE__ */z("div",{className:"es-copy-bar",role:"group","aria-label":a??d.formatting,children:[p.map(e=>{const t=i?.[e.style]??V[e.style],r=u===e.style||Boolean(s?.[e.style]);/* @__PURE__ */
7
+ return T("button",{type:"button",onMouseDown:e=>e.preventDefault(),onClick:()=>n(e.style),disabled:l,title:e.title,"aria-label":e.name??e.title,"aria-keyshortcuts":_(e.shortcut),"aria-pressed":s||u?r:void 0,"aria-haspopup":"link"===e.style&&s?"dialog":void 0,"aria-expanded":"link"===e.style&&s?"link"===u:void 0,className:`es-copy-mark${t?" has-glyph":ee[e.style]?` ${ee[e.style]}`:""}${r?" is-active":""}`,children:t??e.label},e.style)}),r?/* @__PURE__ */z($,{children:[
8
+ /* @__PURE__ */T("span",{className:"es-copy-bar-split","aria-hidden":"true"}),r]}):null,o?/* @__PURE__ */T("span",{className:"es-copy-bar-end",children:o}):null]}):null}function ne({target:e,onChange:t}){const n=j(null);return E(()=>{const t=n.current,l=e.current;t&&l&&l.value===t.text&&(n.current=null,l.focus(),l.setSelectionRange(t.start,t.end))}),l=>{const r=l(e.current);t(r.text),n.current={start:r.selectionStart,end:r.selectionEnd,text:r.text}}}function le({value:o,onChange:i,onCommit:a,onCancel:s,multiline:f=!1,placeholder:y,ariaLabel:b,className:g,readOnly:k=!1,rules:v,tools:x=[],writeMark:w,actions:C,align:D,glyphs:N,barLabel:S,renderFooter:E,inputRef:K,barShows:$="always"}){const A=m("copy",e),B=j(null),M=K??B,[R,Y]=L(!1),[O,H]=L(null),G=j(J()).current,Q=j(null);P(()=>{const e=Q.current;e&&o===e.to?Q.current=null:e&&o===e.from||(Q.current=null,G.reset())},[o,G]);const W=e=>{Q.current={from:Q.current?.from??o,to:e},i(e)},V=e=>({text:o,start:e?.selectionStart??O?.start??o.length,end:e?.selectionEnd??O?.end??o.length}),_=ne({target:M,onChange:W}),ee=e=>(H({start:e.selectionStart,end:e.selectionEnd}),e),le=e=>_(t=>(G.record(V(t),"edit",Date.now()),ee(e(t)))),[re,oe]=L(null),ie=v??r,ae="string"==typeof x[0]?c(x):x,se=ae.map(e=>e.style),ce={};if(O)for(const e of se)ce[e]="link"===e?null!==u(o,O.start,O.end):d(o,O.start,O.end,e);const ue=e=>{if("clear"===e)return void le(t=>Z(o,e,t,(e,t,n)=>l(e,t,n,"clear",ie)));if("link"!==e){const t=w??((e,t,n,o)=>l(e,t,n,o,r,A.placeholders));return void le(n=>Z(o,e,n,t))}const t=M.current,n=t?.selectionStart??o.length,i=t?.selectionEnd??n;oe({start:n,end:i,link:u(o,n,i)})},de=D?I(D.allow,A.align):[];/* @__PURE__ */
9
+ return z("div",{className:"es-copy"+(g?` ${g}`:""),onFocus:()=>Y(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||Y(!1)},onKeyDown:e=>{if(k||e.target!==M.current)return;if(e.altKey||e.metaKey===e.ctrlKey)return;const t=e.key.toLowerCase(),n="KeyZ"===e.code||"z"===t,l=("KeyY"===e.code||"y"===t)&&!e.shiftKey;if(n||l)return e.preventDefault(),e.stopPropagation(),r=l||e.shiftKey?"redo":"undo",void _(e=>{const t=V(e),n=G[r](t);return ee(n?{text:n.text,selectionStart:n.start,selectionEnd:n.end}:{text:t.text,selectionStart:t.start,selectionEnd:t.end})});var r;const o=`${e.shiftKey?"shift+":""}${t}`,i=ae.find(e=>e.shortcut===o);i&&(e.preventDefault(),e.stopPropagation(),ue(i.style))},onPaste:e=>{const t=M.current;if(k||!t||e.target!==t)return;e.preventDefault();const n=U({html:e.clipboardData.getData("text/html"),text:e.clipboardData.getData("text/plain")},{doc:t.ownerDocument,multiline:f,rules:ie});le(e=>q(o,n,e))},onSelect:()=>{const e=M.current;e&&e.ownerDocument.activeElement===e&&H({start:e.selectionStart??o.length,end:e.selectionEnd??o.length})},children:["always"===$||R||null!==re?/* @__PURE__ */T(te,{tools:x,disabled:k,actions:C,glyphs:N,ariaLabel:S,pressed:ce,open:re?"link":null,onApply:ue,align:D?/* @__PURE__ */T(t,{options:de,value:D.value,onChange:D.onChange,ariaLabel:A.alignment,disabled:k||D.disabled,fit:F(de)}):null}):null,
10
+ /* @__PURE__ */T(n,{value:o,onInput:e=>{G.record(V(null),"type",Date.now()),W(e)},onCommit:a,onCancel:s,multiline:f,placeholder:y,ariaLabel:b,rules:v,disabled:k,inputRef:M,className:"es-copy-box"}),re?/* @__PURE__ */T(X,{href:re.link?.href??"",editing:null!==re.link,onApply:e=>{const t=re;oe(null),le(()=>h(o,t.start,t.end,e))},onRemove:()=>{const e=re.link;oe(null),e&&le(()=>p(o,e))},onClose:()=>{oe(null),M.current?.focus()}}):null,E?E({focused:R,insert:e=>le(t=>q(o,e,t))}):null]})}export{A as COPY_ALIGNS,R as COPY_ALIGN_FIT,M as COPY_ALIGN_GLYPHS,B as COPY_ALIGN_LABELS,le as CopyBox,te as MarkBar,H as TYPING_BURST_MS,_ as ariaShortcut,I as copyAlignOptions,J as createHistory,q as insertSelection,Z as markSelection,U as pasteToMarkup,ne as useCaretEdit};
@@ -113,28 +113,48 @@
113
113
  transform: scale(1);
114
114
  }
115
115
 
116
- /* An empty slot: a faint dashed cell that adds a block there, and takes a drop. */
116
+ /* An empty slot: a cell that adds a block there, and takes a drop. At rest it
117
+ draws NOTHING — no fill, no border, no label — so what is under it shows as
118
+ on the live page (owner, option B, 2026-10-06: a HeroSlide's empty "groups"
119
+ slot covers the whole slide, and the old pale fill hid the picture). On hover
120
+ and on keyboard focus: the dashed outline and "+ Add block", and still no
121
+ fill on the cell — the label carries the tint, so it reads over a picture.
122
+ A drag over it lights the whole cell, as before. Touch has no hover: there
123
+ the slot is added to from Layers' "Add" rows. */
117
124
  .es-canvas-empty {
118
125
  position: absolute;
119
126
  box-sizing: border-box;
120
127
  display: flex;
121
128
  align-items: center;
122
129
  justify-content: center;
123
- border: 1.5px dashed var(--es-input-border);
130
+ border: 1.5px dashed transparent;
124
131
  border-radius: 6px;
125
- background: color-mix(in srgb, var(--es-app-bg) 60%, transparent);
126
- color: var(--es-muted);
132
+ background: transparent;
133
+ color: var(--es-accent-text);
127
134
  font: 500 12px/1.3 var(--es-font);
128
135
  cursor: pointer;
129
136
  pointer-events: auto;
130
- transition: border-color 0.12s, background 0.12s, color 0.12s;
137
+ transition: border-color 0.12s, background 0.12s;
138
+ }
139
+ .es-canvas-empty-add {
140
+ padding: 2px 12px;
141
+ border-radius: 999px;
142
+ background: var(--es-accent-tint);
143
+ opacity: 0;
144
+ transition: opacity 0.12s;
131
145
  }
132
146
  .es-canvas-empty:hover,
133
147
  .es-canvas-empty:focus-visible,
134
148
  .es-canvas-empty.is-over {
135
149
  border-color: var(--es-accent);
150
+ }
151
+ .es-canvas-empty.is-over {
136
152
  background: var(--es-accent-tint);
137
- color: var(--es-accent-text);
153
+ }
154
+ .es-canvas-empty:hover .es-canvas-empty-add,
155
+ .es-canvas-empty:focus-visible .es-canvas-empty-add,
156
+ .es-canvas-empty.is-over .es-canvas-empty-add {
157
+ opacity: 1;
138
158
  }
139
159
 
140
160
  /* ── The Add panel's shell ───────────────────────────────────────────────────
@@ -1,7 +1,6 @@
1
- import{DEFAULT_DRAG_WORDS as e}from"../chunk-O2NLQBFX.js";import{scrollBoxOf as t,startAutoScroll as n,isNoOpDrop as l}from"../chunk-6PS6STGA.js";export{AUTO_SCROLL_EDGE,AUTO_SCROLL_MAX_SPEED,autoScrollDelta,autoScrollSpeed,createDragSession,dropOnRow,gapToMoveIndex,isNoOpDrop,scrollBoxOf,scrollParent,startAutoScroll,stepGap,useTreeDrag}from"../chunk-6PS6STGA.js";import{useCanvasLayout as a,useCanvasEvent as r}from"../chunk-MCLBHENY.js";import{framePointToHost as o,elementScale as s,frameRectToLayer as i,clientPointToLayer as c}from"../chunk-ZNCEOSXO.js";import{CloseIcon as d,SearchIcon as u}from"../chunk-PI26YXYD.js";import{parseZoneKey as h}from"../chunk-KRXQM65X.js";import"../chunk-NKB3KVAB.js";import{useRef as p,useEffect as m,useState as f,useCallback as g,useMemo as b,useSyncExternalStore as y,useId as v}from"react";import{jsxs as x,jsx as k}from"react/jsx-runtime";var w=(e,t,n)=>t>=e.left&&t<=e.left+e.width&&n>=e.top&&n<=e.top+e.height,N=e=>e.width*e.height;function D(e,t,n){let l=null;for(const a of e)w(a.box,t,n)&&(!l||N(a.box)<=N(l.box))&&(l=a);return l}function S(e,t,n){const l="x"===e.axis?t:n;let a=0;for(const t of e.children){l>("x"===e.axis?t.left+t.width/2:t.top+t.height/2)&&(a+=1)}return a}function A(e,t){const n=e.children;if("x"===e.axis){const l=n[t-1],a=n[t],r=l&&a?(l.left+l.width+a.left)/2:l?l.left+l.width:a?a.left:e.box.left,o=a??l??e.box;return{left:r-1,top:o.top,width:2,height:o.height}}const l=n[t-1],a=n[t],r=l&&a?(l.top+l.height+a.top)/2:l?l.top+l.height:a?a.top:e.box.top;return{left:e.box.left,top:r-1,width:e.box.width,height:2}}function T(e,t,n,l,a=()=>!1){const r=e.filter(e=>w(e.box,t,n)).sort((e,t)=>N(e.box)-N(t.box));for(const e of r){const r=S(e,t,n),o={...e.list,index:r};if(a(o))return null;if(l(o))return{zone:e,to:o,line:A(e,r)}}return null}function z(e,t=e.key){const n=[];for(let l=1;l<e.children.length;l++){const a=e.children[l-1],r=e.children[l],o=a.top+a.height;n.push({key:`${t}:${l}`,place:{...e.list,index:l},box:{left:e.box.left,top:o,width:e.box.width,height:Math.max(r.top-o,0)}})}return n}var C={nodes:[],zones:[]},E="data-puck-dropzone",L="data-puck-component";function O(e,t){if(e.length>=2){const[t,n]=e;return Math.abs(n.top-t.top)<Math.min(t.height,n.height)/2&&n.left>t.left?"x":"y"}const n=t.ownerDocument.defaultView?.getComputedStyle(t);return n&&n.display.includes("flex")&&n.flexDirection.startsWith("row")?"x":"y"}function j(e,t){const{frame:n,document:l}=e,a=e=>i(n,function(e){const t=e.getBoundingClientRect();return{left:t.left,top:t.top,width:t.width,height:t.height}}(e),t),r=[],o=[];for(const e of l.querySelectorAll(`[${E}]`)){const t=e.getAttribute(E)??"";let n;try{n=h(t)}catch{continue}const l=[...e.querySelectorAll(`[${L}]`)].filter(t=>t.parentElement?.closest(`[${E}]`)===e),s=l.map(a);o.push({key:t,list:n,box:a(e),axis:O(s,e),children:s}),l.forEach((e,t)=>{const l=e.getAttribute(L);l&&r.push({id:l,place:{...n,index:t},box:s[t]})})}return{nodes:r,zones:o}}var B=140,M=e=>({left:e.left,top:e.top,width:e.width,height:e.height});function K(i){const{canvas:d,session:u,readOnly:h,words:v=e.canvas}=i,w=p(i);m(()=>{w.current=i});const N=p(null),S=a(d),[A,z]=f(0),E=g(()=>z(e=>e+1),[]),[L,O]=f(C);m(()=>{const e=N.current;d&&e&&O((w.current.measure??j)(d,e))},[d,S,i.revision,A]);const B=i.model,K=b(()=>B(L),[B,L]),X=y(u.subscribe,u.shown,u.shown),[P,$]=f(null),[R,Y]=f(null),_=p(null),G=()=>{_.current&&clearTimeout(_.current),_.current=null},q=()=>{G(),_.current=setTimeout(()=>{u.get()||$(null)},140)};m(()=>G,[]),r(d,"mousemove",e=>{const t=N.current;if(!d||!t||w.current.readOnly||u.get())return;G();const n=o(d.frame,e.clientX,e.clientY,t),l=s(t),a=D(K.sources,n.x/l,n.y/l);$(e=>e?.key===a?.key&&e?.box===a?.box?e:a)}),r(d,"mouseout",e=>{e.relatedTarget||q()}),r(d,"mouseover",e=>{e.relatedTarget||E()});const I=p(null),Z=g(()=>{I.current?.(),I.current=null,Y(null)},[]);m(()=>u.subscribe(()=>{u.get()?E():Z()}),[u,Z,E]),m(()=>Z,[Z]);const F=e=>{const t=u.get(),n=N.current;if(!t||!n)return null;const a=c(n,e.clientX,e.clientY),r=T(K.zones,a.x,a.y,e=>w.current.canDrop(t.item,e),e=>!!t.from&&l(t.from,e));return r?{h:t,t:r}:null},Q={onDragEnter:e=>{if(I.current)return;const l=t(e.currentTarget.parentElement?.parentElement??null);I.current=l?n(l):null},onDragOver:e=>{const t=F(e);if(!t)return void Y(null);e.preventDefault(),e.dataTransfer.dropEffect=/move|all|uninitialized/i.test(e.dataTransfer.effectAllowed)?"move":"copy";const n={zoneKey:t.t.zone.key,line:t.t.line,axis:t.t.zone.axis};Y(e=>e&&e.zoneKey===n.zoneKey&&e.line.left===n.line.left&&e.line.top===n.line.top?e:n)},onDragLeave:e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||Y(null)},onDrop:e=>{const t=F(e);t&&(e.preventDefault(),u.end(),Z(),w.current.onDrop(t.h.item,t.t.to))}},U={draggable:!h&&!!P,onMouseEnter:G,onMouseLeave:()=>!u.get()&&q(),onDragStart:e=>{if(P&&!h){u.start({key:P.key,item:P.item,from:P.from}),e.dataTransfer.effectAllowed="move";try{e.dataTransfer.setData("text/plain",P.key)}catch{}}else e.preventDefault()},onDragEnd:()=>{u.end(),Z()},onClick:()=>{P&&!h&&w.current.onPick?.(P.item)}},{seams:V=[]}=K,H=K.zones.filter(e=>0===e.children.length);/* @__PURE__ */
2
- return x("div",{ref:N,className:"es-canvas-layer",children:[X||!i.onSeamAdd||h?null:V.map(e=>/* @__PURE__ */k("div",{className:"es-canvas-seam",style:{left:e.box.left,top:e.box.top+e.box.height/2-8,width:e.box.width,height:16},children:/* @__PURE__ */k("button",{type:"button",className:"es-canvas-seam-add",onClick:()=>i.onSeamAdd?.(e.place),children:v.addButton({label:i.seamLabel??v.addSection})})},e.key)),i.onZoneAdd&&!h?H.map(e=>/* @__PURE__ */k("button",{type:"button",className:R?.zoneKey===e.key?"es-canvas-empty is-over":"es-canvas-empty",style:M(e.box),onClick:()=>i.onZoneAdd?.({...e.list,index:0}),children:v.addButton({label:i.zoneAddLabel??v.addBlock})},e.key)):null,X?/* @__PURE__ */k("div",{className:"es-canvas-catch",...Q}):null,R&&!H.some(e=>e.key===R.zoneKey)?/* @__PURE__ */k("div",{className:`es-canvas-line is-${R.axis}`,style:M(R.line)}):null,
3
- /* @__PURE__ */x("div",{className:["es-canvas-handle",P&&!h?"is-shown":"",X?"is-dragging":""].filter(Boolean).join(" "),style:P?{left:P.box.left+2,top:Math.max(P.box.top-11,0)}:void 0,title:P?P.title??v.handle({label:P.label}):void 0,...U,children:[
4
- /* @__PURE__ */k("span",{className:"es-canvas-grip","aria-hidden":"true",children:"⋮⋮"}),P?.label]})]})}var X=e=>e.tiles.length>0&&e.tiles.every(e=>null!=e.cover);function P({groups:t,session:n,itemFor:l,onInsert:a,at:r,hint:o,searchLabel:s,readOnly:i,words:c=e.add}){const h=o??c.hint,p=s??c.search,[m,g]=f(""),b=v(),y=m.trim().toLowerCase(),w=t.map(e=>({...e,tiles:y?e.tiles.filter(e=>((e,t)=>e.label.toLowerCase().includes(t)||(e.keywords??[]).some(e=>e.toLowerCase().includes(t)))(e,y)):e.tiles})).filter(e=>e.tiles.length>0);/* @__PURE__ */
1
+ import{DEFAULT_DRAG_WORDS as e}from"../chunk-O2NLQBFX.js";import{scrollBoxOf as t,startAutoScroll as n,isNoOpDrop as l}from"../chunk-6PS6STGA.js";export{AUTO_SCROLL_EDGE,AUTO_SCROLL_MAX_SPEED,autoScrollDelta,autoScrollSpeed,createDragSession,dropOnRow,gapToMoveIndex,isNoOpDrop,scrollBoxOf,scrollParent,startAutoScroll,stepGap,useTreeDrag}from"../chunk-6PS6STGA.js";import{useCanvasLayout as a,useCanvasEvent as r}from"../chunk-MCLBHENY.js";import{framePointToHost as o,elementScale as s,frameRectToLayer as i,clientPointToLayer as c}from"../chunk-ZNCEOSXO.js";import{CloseIcon as d,SearchIcon as u}from"../chunk-PI26YXYD.js";import{parseZoneKey as h}from"../chunk-KRXQM65X.js";import"../chunk-NKB3KVAB.js";import{useRef as p,useEffect as m,useState as f,useCallback as g,useMemo as b,useSyncExternalStore as y,useId as v}from"react";import{jsxs as x,jsx as k}from"react/jsx-runtime";var w=(e,t,n)=>t>=e.left&&t<=e.left+e.width&&n>=e.top&&n<=e.top+e.height,N=e=>e.width*e.height;function A(e,t,n){let l=null;for(const a of e)w(a.box,t,n)&&(!l||N(a.box)<=N(l.box))&&(l=a);return l}function D(e,t,n){const l="x"===e.axis?t:n;let a=0;for(const t of e.children){l>("x"===e.axis?t.left+t.width/2:t.top+t.height/2)&&(a+=1)}return a}function S(e,t){const n=e.children;if("x"===e.axis){const l=n[t-1],a=n[t],r=l&&a?(l.left+l.width+a.left)/2:l?l.left+l.width:a?a.left:e.box.left,o=a??l??e.box;return{left:r-1,top:o.top,width:2,height:o.height}}const l=n[t-1],a=n[t],r=l&&a?(l.top+l.height+a.top)/2:l?l.top+l.height:a?a.top:e.box.top;return{left:e.box.left,top:r-1,width:e.box.width,height:2}}function z(e,t,n,l,a=()=>!1){const r=e.filter(e=>w(e.box,t,n)).sort((e,t)=>N(e.box)-N(t.box));for(const e of r){const r=D(e,t,n),o={...e.list,index:r};if(a(o))return null;if(l(o))return{zone:e,to:o,line:S(e,r)}}return null}function T(e,t=e.key){const n=[];for(let l=1;l<e.children.length;l++){const a=e.children[l-1],r=e.children[l],o=a.top+a.height;n.push({key:`${t}:${l}`,place:{...e.list,index:l},box:{left:e.box.left,top:o,width:e.box.width,height:Math.max(r.top-o,0)}})}return n}var C={nodes:[],zones:[]},E="data-puck-dropzone",L="data-puck-component";function O(e,t){if(e.length>=2){const[t,n]=e;return Math.abs(n.top-t.top)<Math.min(t.height,n.height)/2&&n.left>t.left?"x":"y"}const n=t.ownerDocument.defaultView?.getComputedStyle(t);return n&&n.display.includes("flex")&&n.flexDirection.startsWith("row")?"x":"y"}function j(e,t){const{frame:n,document:l}=e,a=e=>i(n,function(e){const t=e.getBoundingClientRect();return{left:t.left,top:t.top,width:t.width,height:t.height}}(e),t),r=[],o=[];for(const e of l.querySelectorAll(`[${E}]`)){const t=e.getAttribute(E)??"";let n;try{n=h(t)}catch{continue}const l=[...e.querySelectorAll(`[${L}]`)].filter(t=>t.parentElement?.closest(`[${E}]`)===e),s=l.map(a);o.push({key:t,list:n,box:a(e),axis:O(s,e),children:s}),l.forEach((e,t)=>{const l=e.getAttribute(L);l&&r.push({id:l,place:{...n,index:t},box:s[t]})})}return{nodes:r,zones:o}}var B="data-es-empty-cell",M="data-puck-dropzone",$=140,K=e=>({left:e.left,top:e.top,width:e.width,height:e.height});function X(i){const{canvas:d,session:u,readOnly:h,words:v=e.canvas}=i,w=p(i);m(()=>{w.current=i});const N=p(null),D=a(d),[S,T]=f(0),E=g(()=>T(e=>e+1),[]),[L,O]=f(C);m(()=>{const e=N.current;d&&e&&O((w.current.measure??j)(d,e))},[d,D,i.revision,S]);const $=i.model,X=b(()=>$(L),[$,L]),P=y(u.subscribe,u.shown,u.shown),[q,R]=f(null),[Y,_]=f(null),G=p(null),I=()=>{G.current&&clearTimeout(G.current),G.current=null},Z=()=>{I(),G.current=setTimeout(()=>{u.get()||R(null)},140)};m(()=>I,[]),r(d,"mousemove",e=>{const t=N.current;if(!d||!t||w.current.readOnly||u.get())return;I();const n=o(d.frame,e.clientX,e.clientY,t),l=s(t),a=A(X.sources,n.x/l,n.y/l);R(e=>e?.key===a?.key&&e?.box===a?.box?e:a)}),r(d,"mouseout",e=>{e.relatedTarget||Z()}),r(d,"mouseover",e=>{e.relatedTarget||E()});const F=p(null),Q=g(()=>{F.current?.(),F.current=null,_(null)},[]);m(()=>u.subscribe(()=>{u.get()?E():Q()}),[u,Q,E]),m(()=>Q,[Q]);const U=e=>{const t=u.get(),n=N.current;if(!t||!n)return null;const a=c(n,e.clientX,e.clientY),r=z(X.zones,a.x,a.y,e=>w.current.canDrop(t.item,e),e=>!!t.from&&l(t.from,e));return r?{h:t,t:r}:null},V={onDragEnter:e=>{if(F.current)return;const l=t(e.currentTarget.parentElement?.parentElement??null);F.current=l?n(l):null},onDragOver:e=>{const t=U(e);if(!t)return void _(null);e.preventDefault(),e.dataTransfer.dropEffect=/move|all|uninitialized/i.test(e.dataTransfer.effectAllowed)?"move":"copy";const n={zoneKey:t.t.zone.key,line:t.t.line,axis:t.t.zone.axis};_(e=>e&&e.zoneKey===n.zoneKey&&e.line.left===n.line.left&&e.line.top===n.line.top?e:n)},onDragLeave:e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||_(null)},onDrop:e=>{const t=U(e);t&&(e.preventDefault(),u.end(),Q(),w.current.onDrop(t.h.item,t.t.to))}},H={draggable:!h&&!!q,onMouseEnter:I,onMouseLeave:()=>!u.get()&&Z(),onDragStart:e=>{if(q&&!h){u.start({key:q.key,item:q.item,from:q.from}),e.dataTransfer.effectAllowed="move";try{e.dataTransfer.setData("text/plain",q.key)}catch{}}else e.preventDefault()},onDragEnd:()=>{u.end(),Q()},onClick:()=>{q&&!h&&w.current.onPick?.(q.item)}},{seams:W=[]}=X,J=X.zones.filter(e=>0===e.children.length),ee=i.onZoneAdd&&!h?J:[],te=ee.map(e=>e.key).join("\n");return m(()=>{const e=d?.document;if(!e)return;const t=new Set(te?te.split("\n"):[]);for(const n of e.querySelectorAll(`[${M}]`))n.toggleAttribute(B,t.has(n.getAttribute(M)??""));return()=>{for(const t of e.querySelectorAll(`[${B}]`))t.removeAttribute(B)}},[d,te,L,D,S]),/* @__PURE__ */x("div",{ref:N,className:"es-canvas-layer",children:[P||!i.onSeamAdd||h?null:W.map(e=>/* @__PURE__ */k("div",{className:"es-canvas-seam",style:{left:e.box.left,top:e.box.top+e.box.height/2-8,width:e.box.width,height:16},children:/* @__PURE__ */k("button",{type:"button",className:"es-canvas-seam-add",onClick:()=>i.onSeamAdd?.(e.place),children:v.addButton({label:i.seamLabel??v.addSection})})},e.key)),ee.length?ee.map(e=>/* @__PURE__ */k("button",{type:"button",className:Y?.zoneKey===e.key?"es-canvas-empty is-over":"es-canvas-empty",style:K(e.box),onClick:()=>i.onZoneAdd?.({...e.list,index:0}),children:/* @__PURE__ */k("span",{className:"es-canvas-empty-add",children:v.addButton({label:i.zoneAddLabel??v.addBlock})})},e.key)):null,P?/* @__PURE__ */k("div",{className:"es-canvas-catch",...V}):null,Y&&!J.some(e=>e.key===Y.zoneKey)?/* @__PURE__ */k("div",{className:`es-canvas-line is-${Y.axis}`,style:K(Y.line)}):null,
2
+ /* @__PURE__ */x("div",{className:["es-canvas-handle",q&&!h?"is-shown":"",P?"is-dragging":""].filter(Boolean).join(" "),style:q?{left:q.box.left+2,top:Math.max(q.box.top-11,0)}:void 0,title:q?q.title??v.handle({label:q.label}):void 0,...H,children:[
3
+ /* @__PURE__ */k("span",{className:"es-canvas-grip","aria-hidden":"true",children:"⋮⋮"}),q?.label]})]})}var P=e=>e.tiles.length>0&&e.tiles.every(e=>null!=e.cover);function q({groups:t,session:n,itemFor:l,onInsert:a,at:r,hint:o,searchLabel:s,readOnly:i,words:c=e.add}){const h=o??c.hint,p=s??c.search,[m,g]=f(""),b=v(),y=m.trim().toLowerCase(),w=t.map(e=>({...e,tiles:y?e.tiles.filter(e=>((e,t)=>e.label.toLowerCase().includes(t)||(e.keywords??[]).some(e=>e.toLowerCase().includes(t)))(e,y)):e.tiles})).filter(e=>e.tiles.length>0);/* @__PURE__ */
5
4
  return x("div",{className:"es-add",children:[r?/* @__PURE__ */x("div",{className:"es-add-at",role:"status",children:[
6
5
  /* @__PURE__ */k("span",{children:r.label}),
7
6
  /* @__PURE__ */k("button",{type:"button",className:"es-add-at-clear","aria-label":c.stop,title:c.stop,onClick:r.onClear,children:/* @__PURE__ */k(d,{size:12,"aria-hidden":"true"})})]}):null,
@@ -14,5 +13,5 @@ return x("div",{className:"es-add",children:[r?/* @__PURE__ */x("div",{className
14
13
  /* @__PURE__ */x("div",{className:"es-add-group-head",children:[
15
14
  /* @__PURE__ */k("span",{className:"es-add-group-title",children:e.title}),
16
15
  /* @__PURE__ */k("span",{className:"es-add-group-count",children:e.tiles.length})]}),
17
- /* @__PURE__ */k("div",{className:X(e)?"es-add-grid is-cards":"es-add-grid",children:e.tiles.map(e=>{/* @__PURE__ */return x("button",{type:"button",className:null!=e.cover?"es-add-tile has-cover":"es-add-tile",draggable:!i,"aria-disabled":i||void 0,"aria-label":c.tile({label:e.label}),title:i?void 0:e.title??c.tile({label:e.label}),onDragStart:(t=e.type,e=>{if(i)e.preventDefault();else{n.start({key:`new:${t}`,item:l(t)}),e.dataTransfer.effectAllowed="copy";try{e.dataTransfer.setData("text/plain",t)}catch{}}}),onDragEnd:()=>n.end(),onClick:()=>!i&&a(e.type),children:[null!=e.cover?/* @__PURE__ */k("span",{className:"es-add-tile-cover","aria-hidden":"true",children:e.cover}):e.icon?/* @__PURE__ */k("span",{className:"es-add-tile-glyph","aria-hidden":"true",children:e.icon}):null,
18
- /* @__PURE__ */k("span",{className:"es-add-tile-label",children:e.label})]},e.type);var t})})]},e.title))]})}export{P as AddPanel,K as CanvasDragLayer,C as EMPTY_MEASURE,B as HANDLE_GRACE_MS,T as canvasTarget,w as contains,S as gapInZone,A as gapLine,j as measureCanvas,D as pickSource,z as seamsBetween};
16
+ /* @__PURE__ */k("div",{className:P(e)?"es-add-grid is-cards":"es-add-grid",children:e.tiles.map(e=>{/* @__PURE__ */return x("button",{type:"button",className:null!=e.cover?"es-add-tile has-cover":"es-add-tile",draggable:!i,"aria-disabled":i||void 0,"aria-label":c.tile({label:e.label}),title:i?void 0:e.title??c.tile({label:e.label}),onDragStart:(t=e.type,e=>{if(i)e.preventDefault();else{n.start({key:`new:${t}`,item:l(t)}),e.dataTransfer.effectAllowed="copy";try{e.dataTransfer.setData("text/plain",t)}catch{}}}),onDragEnd:()=>n.end(),onClick:()=>!i&&a(e.type),children:[null!=e.cover?/* @__PURE__ */k("span",{className:"es-add-tile-cover","aria-hidden":"true",children:e.cover}):e.icon?/* @__PURE__ */k("span",{className:"es-add-tile-glyph","aria-hidden":"true",children:e.icon}):null,
17
+ /* @__PURE__ */k("span",{className:"es-add-tile-label",children:e.label})]},e.type);var t})})]},e.title))]})}export{q as AddPanel,X as CanvasDragLayer,C as EMPTY_MEASURE,$ as HANDLE_GRACE_MS,z as canvasTarget,w as contains,D as gapInZone,S as gapLine,j as measureCanvas,A as pickSource,T as seamsBetween};
@@ -42,6 +42,15 @@
42
42
  background: color-mix(in srgb, var(--es-accent, #2563eb) 6%, transparent);
43
43
  outline: 2px dashed color-mix(in srgb, var(--es-accent, #2563eb) 35%, transparent);
44
44
  }
45
+ /* …except an empty list the drag layer draws its "+ Add block" cell over
46
+ (`data-es-empty-cell`, efficient-easel/drag): at rest that slot draws
47
+ NOTHING, and the cell shows on hover (owner design B, 2026-10-06). The
48
+ states above still draw on it. A rule of its own rather than a :not() on
49
+ `.es-zone:empty`: hosts read that selector by its spelling. */
50
+ .es-zone:empty[data-es-empty-cell]:not(.is-area-selected):not(.is-hovering-area:not(.is-root)) {
51
+ background: none;
52
+ outline: none;
53
+ }
45
54
 
46
55
  .es-canvas-outline {
47
56
  pointer-events: none;
@@ -1 +1 @@
1
- export{GoldLayer,GoldTextInput,goldSegments}from"../chunk-CERTFXCV.js";import"../chunk-6OPSJGAI.js";var e={accent:"var(--gold, #c9a461)",quiet:"var(--es-muted, #6b7280)",caret:"var(--es-text, #111827)",placeholder:"var(--es-field-placeholder, #9ca3af)",delimiterOpacity:"0.35",delimiterRestingOpacity:"0.25",boldShadow:"0 0 0.4px currentColor",italicDecoration:"underline dotted",strikeDecoration:"line-through",pad:"0"},t={accent:"--es-gold-accent",quiet:"--es-gold-quiet",caret:"--es-gold-caret",placeholder:"--es-gold-placeholder",delimiterOpacity:"--es-gold-delim-opacity",delimiterRestingOpacity:"--es-gold-delim-resting-opacity",boldShadow:"--es-gold-bold-shadow",italicDecoration:"--es-gold-italic-decoration",strikeDecoration:"--es-gold-strike-decoration",pad:"--es-gold-pad"};export{t as goldCssVars,e as goldTokens};
1
+ export{GoldLayer,GoldTextInput,goldSegments}from"../chunk-JYPOOHII.js";import"../chunk-SJQG5ENJ.js";var e={accent:"var(--gold, #c9a461)",quiet:"var(--es-muted, #6b7280)",caret:"var(--es-text, #111827)",placeholder:"var(--es-field-placeholder, #9ca3af)",delimiterOpacity:"0.35",delimiterRestingOpacity:"0.25",boldShadow:"0 0 0.4px currentColor",italicDecoration:"underline dotted",strikeDecoration:"line-through",pad:"0"},t={accent:"--es-gold-accent",quiet:"--es-gold-quiet",caret:"--es-gold-caret",placeholder:"--es-gold-placeholder",delimiterOpacity:"--es-gold-delim-opacity",delimiterRestingOpacity:"--es-gold-delim-resting-opacity",boldShadow:"--es-gold-bold-shadow",italicDecoration:"--es-gold-italic-decoration",strikeDecoration:"--es-gold-strike-decoration",pad:"--es-gold-pad"};export{t as goldCssVars,e as goldTokens};
@@ -43,7 +43,36 @@
43
43
  *
44
44
  * [words](href) a link — safe addresses only ({@link isSafeLinkHref})
45
45
  * - words a bullet line, one level
46
- * **a _b_ a** one run inside another, one level
46
+ * 1. words a numbered line, one level: 1-3 digits, ". ", words
47
+ * **a _b_ a** one run inside another, up to four levels
48
+ *
49
+ * [words]{underline} underline
50
+ * [words]{sup} superscript
51
+ * [words]{sub} subscript
52
+ * [words]{color=name} a theme colour, by NAME ({@link isColorName})
53
+ *
54
+ * THE SPANS AND THE NUMBERED LINE (plan step E1, approved by GG 2026-10-06)
55
+ * are the final text box's marks. One shape for all four, so one reading rule:
56
+ * `[`, words, `]`, then EXACTLY one of those blocks. Anything else after the
57
+ * `]` — `{foo}`, `{color=#ff0000}`, a merge tag's `{{` — is not a span, and the
58
+ * whole thing stays as typed. Two marks on the same words nest
59
+ * (`[[x]{sup}]{color=accent}`); one block never holds two.
60
+ *
61
+ * Why these cannot clash with an old mark: no old rule closes on `]{` (a link
62
+ * needs `](`), and the campaign's legacy `[phrase]` italic steps back from a
63
+ * span block, the way it steps back from a link (`notBeforeBlock`). No inline
64
+ * rule opens on a digit. Production held neither shape when they were chosen:
65
+ * 0 of 24,233 text values contained `]{`, and none had a line starting with a
66
+ * number and `.` or `)`.
67
+ *
68
+ * Not chosen: `^x^` / `~x~` (one character from Quiet `^^` and strike `~~`,
69
+ * and `~20 min` is ordinary copy), `__x__` (pinned as italic below, and
70
+ * CommonMark's bold) and `++x++` (the old Strong).
71
+ *
72
+ * Only the tree ({@link parseMarkup}) reads them. The flat
73
+ * {@link tokenizeInline} — the old renderers' reading — keeps them as text, as
74
+ * it keeps links: an email or a page drawn before its renderer learns them
75
+ * prints the delimiters. No toolbar button writes them yet.
47
76
  *
48
77
  * EVERY READING IS LINE BY LINE: a run never crosses a line break. The email
49
78
  * always read this way; the editor's painter and the storefront used to read
@@ -87,21 +116,32 @@
87
116
  */
88
117
  /** A style a toolbar button can apply. The first six are inline marks; then
89
118
  * the composer-only affordances (a link and the three line prefixes), which
90
- * only a renderer that draws block content can honour; and `clear`, which
91
- * writes no mark at all — it takes them off ({@link clearMarks}). */
92
- type MarkStyle = 'bold' | 'italic' | 'strike' | 'code' | 'highlight' | 'quiet' | 'link' | 'bullet' | 'number' | 'quote' | 'clear';
119
+ * only a renderer that draws block content can honour; `clear`, which
120
+ * writes no mark at all — it takes them off ({@link clearMarks}); and the
121
+ * three spans of the final text box (E1), which no button in
122
+ * {@link MARKUP_TOOLS} offers yet. A colour carries a name, so it is written
123
+ * by {@link applyColor}, not here. */
124
+ type MarkStyle = 'bold' | 'italic' | 'strike' | 'code' | 'highlight' | 'quiet' | 'link' | 'bullet' | 'number' | 'quote' | 'clear' | 'underline' | 'sup' | 'sub';
125
+ /** What a span means: `[words]{underline}`, `{sup}`, `{sub}` or
126
+ * `{color=name}`. Only the tree reads these; {@link InlineKind} is the flat
127
+ * reading's, which never makes one. */
128
+ type SpanKind = 'underline' | 'sup' | 'sub' | 'color';
93
129
  /** What a parsed run MEANS. `accent` is the storefront/campaign brand colour —
94
130
  * the legacy `*phrase*` — and `highlight` is its standard-markdown successor;
95
131
  * both resolve to the same paint, which is what makes converting stored copy
96
132
  * from one to the other invisible. */
97
133
  type InlineKind = 'text' | 'bold' | 'italic' | 'strike' | 'code' | 'highlight' | 'accent' | 'quiet';
134
+ /** A theme colour's name as a span saves it: lowercase letters, digits and
135
+ * `-`, starting with a letter (`accent`, `brand-2`). Never a hex: a colour is
136
+ * the theme's, so changing the theme recolours the words. */
137
+ declare function isColorName(name: string): boolean;
98
138
  /**
99
139
  * The words a press WRITES when nothing is selected — `**bold text**`, left
100
140
  * selected so the next keystroke replaces it. English unless the caller of
101
141
  * {@link applyMark} hands in its own (0.95.0: a host in another language).
102
142
  * They are words put in the box, not rules: nothing here changes what parses.
103
143
  */
104
- type MarkPlaceholders = Record<'bold' | 'italic' | 'strike' | 'code' | 'highlight' | 'quiet' | 'link', string>;
144
+ type MarkPlaceholders = Record<'bold' | 'italic' | 'strike' | 'code' | 'highlight' | 'quiet' | 'link', string> & Partial<Record<'underline' | 'sup' | 'sub' | 'color', string>>;
105
145
  declare const MARK_PLACEHOLDERS: MarkPlaceholders;
106
146
  interface WrapResult {
107
147
  text: string;
@@ -119,6 +159,17 @@ interface WrapResult {
119
159
  * and the campaign designer, where the asterisk means colour, not slant.
120
160
  */
121
161
  declare function applyMark(text: string, start: number, end: number, style: MarkStyle, rules?: readonly InlineRule[], placeholders?: MarkPlaceholders): WrapResult;
162
+ /**
163
+ * Colour `text[start:end]` with the theme colour `name`, writing
164
+ * `[words]{color=name}` and leaving the words selected. On words that are
165
+ * already exactly one colour span it changes the name; `null` takes the colour
166
+ * off. A name {@link isColorName} refuses changes nothing — a hex or a typo is
167
+ * never saved as a block the reader would print as text.
168
+ *
169
+ * Separate from {@link applyMark} because a colour carries a value, as a link
170
+ * does ({@link writeLink}).
171
+ */
172
+ declare function applyColor(text: string, start: number, end: number, name: string | null, placeholders?: MarkPlaceholders): WrapResult;
122
173
  /**
123
174
  * True when `text[start:end]` is ALREADY wrapped in `style`'s own fence — the
124
175
  * very test {@link applyMark} uses to decide that a press unwraps. So a button
@@ -226,6 +277,14 @@ interface InlineRule {
226
277
  * more rule field and no new branch in {@link tokenizeInline}.
227
278
  */
228
279
  readonly notBefore?: string;
280
+ /**
281
+ * True when the run may not close right before a span block (`{sup}`,
282
+ * `{color=accent}`, …). The campaign's legacy `[phrase]` needs it for the
283
+ * reason it needs `notBefore: '('`: without it `[x]{sup}` would read as an
284
+ * italic `x` followed by a printed `{sup}`. Only the four exact blocks count,
285
+ * so `[x]{{first_name}}` and `[x]{foo}` read as they always did.
286
+ */
287
+ readonly notBeforeBlock?: boolean;
229
288
  }
230
289
  /**
231
290
  * The standard-markdown marks, shared by every product.
@@ -322,12 +381,14 @@ interface MarkupText {
322
381
  text: string;
323
382
  }
324
383
  /** A delimited run. `open` and `close` are the delimiters that were actually
325
- * saved — `#` for a legacy campaign bold, `**` for the standard one — so the
326
- * tree writes back the same bytes it was read from. */
384
+ * saved — `#` for a legacy campaign bold, `**` for the standard one, `[` and
385
+ * `]{sup}` for a span — so the tree writes back the same bytes it was read
386
+ * from. `color` is the theme colour's name, on a `color` span only. */
327
387
  interface MarkupRun {
328
- kind: InlineRule['kind'];
388
+ kind: InlineRule['kind'] | SpanKind;
329
389
  open: string;
330
390
  close: string;
391
+ color?: string;
331
392
  children: MarkupNode[];
332
393
  }
333
394
  /** `[words](href)`. Only made when {@link isSafeLinkHref} passes. */
@@ -338,9 +399,12 @@ interface MarkupLink {
338
399
  }
339
400
  type MarkupNode = MarkupText | MarkupRun | MarkupLink;
340
401
  /** One line of the saved string. `bullet` means it was saved as `- words`;
341
- * `children` hold what follows the `- `. */
402
+ * `number` holds the digits of a line saved as `12. words`, as typed (`01`
403
+ * stays `01`), and is null on every other line. `children` hold what follows
404
+ * the prefix. A line built by hand may leave `number` out: it means null. */
342
405
  interface MarkupLine {
343
406
  bullet: boolean;
407
+ number?: string | null;
344
408
  children: MarkupNode[];
345
409
  }
346
410
  /**
@@ -361,10 +425,14 @@ declare function isSafeLinkHref(href: string): boolean;
361
425
  * - A run never crosses a line break.
362
426
  * - A line that starts with `- ` and has words after it is a bullet. One level
363
427
  * only: an indented ` - ` is plain text.
428
+ * - A line that starts with 1-3 digits, `. ` and words is numbered, the digits
429
+ * kept as typed. One level only, as bullets.
364
430
  * - `[words](href)` is a link when {@link isSafeLinkHref} passes; otherwise the
365
431
  * whole thing stays plain text.
366
- * - A run's words are read once more, so `**bold _with italic_**` is italic
367
- * inside bold. One level only: a third level stays as typed.
432
+ * - `[words]{underline}`, `{sup}`, `{sub}` and `{color=name}` are spans; any
433
+ * other block stays plain text.
434
+ * - A run's words are read again, so `**bold _with italic_**` is italic inside
435
+ * bold. Four levels: a fifth stays as typed.
368
436
  *
369
437
  * Nothing is lost: {@link serializeMarkup} writes back the exact bytes.
370
438
  */
@@ -378,22 +446,25 @@ declare function serializeMarkup(lines: readonly MarkupLine[]): string;
378
446
  *
379
447
  * `open` and `close` are the delimiters that were saved (`#` for a legacy
380
448
  * campaign bold), or, for a run made in the editor, the toolbar's own fence.
381
- * A link's `close` is `](href)`.
449
+ * A link's `close` is `](href)`, a span's `]{sup}` or `]{color=name}`.
382
450
  */
383
451
  interface MarkSpan {
384
452
  id: number;
385
- kind: InlineRule['kind'] | 'link';
453
+ kind: InlineRule['kind'] | SpanKind | 'link';
386
454
  open: string;
387
455
  close: string;
388
456
  href?: string;
457
+ color?: string;
389
458
  }
390
459
  /**
391
460
  * A NEW run, as the toolbar writes it: `**` for bold, `_` for italic, and so on
392
- * ({@link applyMark}'s own fences), or a link to `href`. Null for a style that
393
- * writes no run (a line prefix, clear). A paste filter or an editor making a
394
- * run asks here, so no delimiter is spelled outside this module (E8).
461
+ * ({@link applyMark}'s own fences), a link to `value`, or a colour span named
462
+ * `value` ({@link isColorName}). Null for a style that writes no run (a line
463
+ * prefix, clear) and for a link or colour with no usable value. A paste filter
464
+ * or an editor making a run asks here, so no delimiter is spelled outside this
465
+ * module (E8).
395
466
  */
396
- declare function spanFor(id: number, style: MarkStyle, href?: string): MarkSpan | null;
467
+ declare function spanFor(id: number, style: MarkStyle | 'color', value?: string): MarkSpan | null;
397
468
  /** One character of the words — never a delimiter — with the runs it sits in,
398
469
  * outside first, and its offset in the saved string. */
399
470
  interface MarkedChar {
@@ -401,9 +472,12 @@ interface MarkedChar {
401
472
  marks: readonly MarkSpan[];
402
473
  at: number;
403
474
  }
404
- /** One line: its bullet flag (the `- ` is not a character) and its words. */
475
+ /** One line: its bullet flag or its number (the `- ` and the `12. ` are not
476
+ * characters) and its words. `number` left out means null, as on
477
+ * {@link MarkupLine}. */
405
478
  interface MarkedLine {
406
479
  bullet: boolean;
480
+ number?: string | null;
407
481
  chars: MarkedChar[];
408
482
  }
409
483
  /**
@@ -433,12 +507,14 @@ declare function writeMarkedLines(lines: readonly MarkedLine[]): {
433
507
  at: number[][];
434
508
  };
435
509
  /** True when two readings hold the same words wearing the same marks — the
436
- * kinds and addresses, not which run or which delimiter. */
510
+ * kinds, addresses, colours and list numbers, not which run or which
511
+ * delimiter. */
437
512
  declare function sameMarks(a: readonly MarkedLine[], b: readonly MarkedLine[]): boolean;
438
513
  /**
439
514
  * Take every mark off `text[start:end]`, keeping the words and any link (a
440
515
  * link has its own Remove). A run the selection only partly covers is split,
441
- * so the rest of it keeps its mark. Bullets stay: they are lines, not marks.
516
+ * so the rest of it keeps its mark. Bullets and numbers stay: they are lines,
517
+ * not marks.
442
518
  *
443
519
  * With nothing selected, the runs the caret touches — the characters either
444
520
  * side of it — come off whole.
@@ -449,4 +525,4 @@ declare function sameMarks(a: readonly MarkedLine[], b: readonly MarkedLine[]):
449
525
  */
450
526
  declare function clearMarks(text: string, start: number, end: number, rules?: readonly InlineRule[]): WrapResult;
451
527
 
452
- export { CAMPAIGN_MARKUP, COPY_FIELD_TOOLS, type InlineKind, type InlineRule, type InlineToken, type LinkSpan, MARKUP_TOOLS, MARK_NAMES, MARK_PLACEHOLDERS, type MarkPlaceholders, type MarkSpan, type MarkStyle, type MarkedChar, type MarkedLine, type MarkupLine, type MarkupLink, type MarkupNode, type MarkupRun, type MarkupText, type MarkupTool, STANDARD_MARKUP, STOREFRONT_MARKUP, type WrapResult, applyMark, clearMarks, findLink, isSafeLinkHref, markedAt, markedLines, markupTools, parseMarkup, removeLink, sameMarks, serializeMarkup, spanFor, stripInline, tokenizeInline, writeLink, writeMarkedLines };
528
+ export { CAMPAIGN_MARKUP, COPY_FIELD_TOOLS, type InlineKind, type InlineRule, type InlineToken, type LinkSpan, MARKUP_TOOLS, MARK_NAMES, MARK_PLACEHOLDERS, type MarkPlaceholders, type MarkSpan, type MarkStyle, type MarkedChar, type MarkedLine, type MarkupLine, type MarkupLink, type MarkupNode, type MarkupRun, type MarkupText, type MarkupTool, STANDARD_MARKUP, STOREFRONT_MARKUP, type SpanKind, type WrapResult, applyColor, applyMark, clearMarks, findLink, isColorName, isSafeLinkHref, markedAt, markedLines, markupTools, parseMarkup, removeLink, sameMarks, serializeMarkup, spanFor, stripInline, tokenizeInline, writeLink, writeMarkedLines };
@@ -1 +1 @@
1
- export{CAMPAIGN_MARKUP,COPY_FIELD_TOOLS,MARKUP_TOOLS,MARK_NAMES,MARK_PLACEHOLDERS,STANDARD_MARKUP,STOREFRONT_MARKUP,applyMark,clearMarks,findLink,isSafeLinkHref,markedAt,markedLines,markupTools,parseMarkup,removeLink,sameMarks,serializeMarkup,spanFor,stripInline,tokenizeInline,writeLink,writeMarkedLines}from"../chunk-6OPSJGAI.js";
1
+ export{CAMPAIGN_MARKUP,COPY_FIELD_TOOLS,MARKUP_TOOLS,MARK_NAMES,MARK_PLACEHOLDERS,STANDARD_MARKUP,STOREFRONT_MARKUP,applyColor,applyMark,clearMarks,findLink,isColorName,isSafeLinkHref,markedAt,markedLines,markupTools,parseMarkup,removeLink,sameMarks,serializeMarkup,spanFor,stripInline,tokenizeInline,writeLink,writeMarkedLines}from"../chunk-SJQG5ENJ.js";
@@ -1 +1 @@
1
- export{DEFAULT_EDITOR_STRINGS,mergeEditorStrings}from"../chunk-OGZFDJ6G.js";import"../chunk-ZAOM6PFH.js";import"../chunk-6WY6ZXJG.js";import"../chunk-GGTPNGFJ.js";import"../chunk-SUO5627P.js";import"../chunk-H4B72XCJ.js";import"../chunk-7A7O2JWQ.js";import"../chunk-WK3AFPXY.js";import"../chunk-H6DDIBQ4.js";import"../chunk-KDIVA6WD.js";import"../chunk-RE4LP46F.js";import"../chunk-2OAZYSWJ.js";import"../chunk-2LUSK32B.js";import"../chunk-6OPSJGAI.js";import"../chunk-O2NLQBFX.js";
1
+ export{DEFAULT_EDITOR_STRINGS,mergeEditorStrings}from"../chunk-JE63JHKO.js";import"../chunk-ZAOM6PFH.js";import"../chunk-6WY6ZXJG.js";import"../chunk-GGTPNGFJ.js";import"../chunk-SUO5627P.js";import"../chunk-H4B72XCJ.js";import"../chunk-7A7O2JWQ.js";import"../chunk-WK3AFPXY.js";import"../chunk-H6DDIBQ4.js";import"../chunk-KDIVA6WD.js";import"../chunk-RE4LP46F.js";import"../chunk-2OAZYSWJ.js";import"../chunk-ZT7M24XD.js";import"../chunk-SJQG5ENJ.js";import"../chunk-O2NLQBFX.js";
@@ -1,2 +1,2 @@
1
- import{DEFAULT_EDITOR_STRINGS as r,mergeEditorStrings as n}from"../chunk-OGZFDJ6G.js";export{DEFAULT_EDITOR_STRINGS,mergeEditorStrings}from"../chunk-OGZFDJ6G.js";import"../chunk-ZAOM6PFH.js";import"../chunk-6WY6ZXJG.js";import"../chunk-GGTPNGFJ.js";import"../chunk-SUO5627P.js";import"../chunk-H4B72XCJ.js";import"../chunk-7A7O2JWQ.js";import"../chunk-WK3AFPXY.js";import"../chunk-H6DDIBQ4.js";import"../chunk-KDIVA6WD.js";import"../chunk-RE4LP46F.js";import"../chunk-2OAZYSWJ.js";import"../chunk-2LUSK32B.js";import"../chunk-6OPSJGAI.js";import{stringsContext as o}from"../chunk-MFIRYGHW.js";import"../chunk-O2NLQBFX.js";import{useContext as t,useMemo as i}from"react";import{jsx as c}from"react/jsx-runtime";function s({value:s,locale:u,children:m}){const e=o(),p=t(e),h=p?.strings??r,j=u??p?.locale??"en",k=i(()=>({strings:n(h,s),locale:j}),[h,s,j]);/* @__PURE__ */
1
+ import{DEFAULT_EDITOR_STRINGS as r,mergeEditorStrings as n}from"../chunk-JE63JHKO.js";export{DEFAULT_EDITOR_STRINGS,mergeEditorStrings}from"../chunk-JE63JHKO.js";import"../chunk-ZAOM6PFH.js";import"../chunk-6WY6ZXJG.js";import"../chunk-GGTPNGFJ.js";import"../chunk-SUO5627P.js";import"../chunk-H4B72XCJ.js";import"../chunk-7A7O2JWQ.js";import"../chunk-WK3AFPXY.js";import"../chunk-H6DDIBQ4.js";import"../chunk-KDIVA6WD.js";import"../chunk-RE4LP46F.js";import"../chunk-2OAZYSWJ.js";import"../chunk-ZT7M24XD.js";import"../chunk-SJQG5ENJ.js";import{stringsContext as o}from"../chunk-MFIRYGHW.js";import"../chunk-O2NLQBFX.js";import{useContext as t,useMemo as i}from"react";import{jsx as c}from"react/jsx-runtime";function s({value:s,locale:u,children:m}){const e=o(),p=t(e),h=p?.strings??r,j=u??p?.locale??"en",k=i(()=>({strings:n(h,s),locale:j}),[h,s,j]);/* @__PURE__ */
2
2
  return c(e.Provider,{value:k,children:m})}function u(){return t(o())?.strings??r}function m(){return t(o())?.locale??"en"}export{s as EditorStringsProvider,m as useEditorLocale,u as useEditorStrings};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efficient-easel",
3
- "version": "0.98.0",
3
+ "version": "0.99.1",
4
4
  "description": "Efficient Easel: the EFFICIENT editors' shared engine and chrome: the saved document as pure functions, the published renderer, and the editor frame, panels, Layers tree, text grammar and type-in-place box. Published as editor-shell up to 0.66.0 and as efficient-editor up to 0.95.0.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Efficient Pty Ltd",
@@ -1 +0,0 @@
1
- var e={bold:{fence:"**",placeholder:"bold text"},italic:{fence:"_",placeholder:"italic text"},strike:{fence:"~~",placeholder:"struck out"},code:{fence:"`",placeholder:"code"},highlight:{fence:"==",placeholder:"highlighted text"},quiet:{fence:"^^",placeholder:"quiet text"}},t={bold:e.bold.placeholder,italic:e.italic.placeholder,strike:e.strike.placeholder,code:e.code.placeholder,highlight:e.highlight.placeholder,quiet:e.quiet.placeholder,link:"link text"},n={bullet:()=>"- ",number:e=>`${e+1}. `,quote:()=>"> "};function l(l,i,r,s,o=u,c=t){if("clear"===s)return Q(l,i,r,o);const a=l.slice(i,r);if("link"===s){const e=a||c.link,t=`[${e}](https://)`;return{text:l.slice(0,i)+t+l.slice(r),selectionStart:i+e.length+3,selectionEnd:i+t.length-1}}const h=n[s];if(h){const e=l.lastIndexOf("\n",Math.max(i-1,0))+1,t=l.indexOf("\n",r),n=-1===t?l.length:t,s=l.slice(e,n).split("\n"),o=s.every((e,t)=>e.startsWith(h(t))),c=s.map((e,t)=>o?e.slice(h(t).length):h(t)+e).join("\n");return{text:l.slice(0,e)+c+l.slice(n),selectionStart:e,selectionEnd:e+c.length}}const{fence:d}=e[s],f=c[s],k=l.slice(Math.max(0,i-d.length),i),p=l.slice(r,r+d.length);if(k===d&&p===d)return{text:l.slice(0,i-d.length)+a+l.slice(r+d.length),selectionStart:i-d.length,selectionEnd:i-d.length+a.length};const g=a||f;return{text:l.slice(0,i)+d+g+d+l.slice(r),selectionStart:i+d.length,selectionEnd:i+d.length+g.length}}function i(t,n,l,i){const r=e[i];if(!r)return!1;const{fence:s}=r;return n>=s.length&&t.slice(n-s.length,n)===s&&t.slice(l,l+s.length)===s}function r(e,t,n){const l=0===t?0:e.lastIndexOf("\n",t-1)+1;for(let i=e.lastIndexOf("[",t);i>=l;i=0===i?-1:e.lastIndexOf("[",i-1)){const t=S(e,i);if(t&&n<=t.end)return{start:i,end:t.end,label:t.label,href:t.href}}return null}function s(e,t,n,l){const i=r(e,t,n),s=i?i.start:t,o=i?i.end:n,c=`[${i?i.label:e.slice(t,n)||l}](${l})`,a=s+c.length;return{text:e.slice(0,s)+c+e.slice(o),selectionStart:a,selectionEnd:a}}function o(e,t){return{text:e.slice(0,t.start)+t.label+e.slice(t.end),selectionStart:t.start,selectionEnd:t.start+t.label.length}}var c=[{style:"bold",label:"B",name:"Strong",title:"Strong · **words** · ⌘B",shortcut:"b"},{style:"italic",label:"I",name:"Italic",title:"Italic · _words_ · ⌘I",shortcut:"i"},{style:"strike",label:"S",name:"Strikethrough",title:"Strikethrough · ~~words~~"},{style:"highlight",label:"◆",name:"Emphasis",title:"Emphasis · ==words=="},{style:"quiet",label:"a",name:"Quiet",title:"Quiet · ^^words^^"},{style:"code",label:"‹›",name:"Code",title:"Code"},{style:"link",label:"🔗",name:"Link",title:"Link · [words](https://…) · ⌘K",shortcut:"k"},{style:"bullet",label:"•",name:"Bulleted list",title:"Bulleted list"},{style:"number",label:"1.",name:"Numbered list",title:"Numbered list"},{style:"quote",label:"❝",name:"Quote",title:"Quote"},{style:"clear",label:"T×",name:"Clear marks",title:"Clear marks · ⌘⇧X",shortcut:"shift+x"}],a={bold:"Strong",highlight:"Emphasis",quiet:"Quiet"};function h(e){return c.filter(t=>e.includes(t.style))}var u=[{open:"**",close:"**",kind:"bold"},{open:"==",close:"==",kind:"highlight"},{open:"~~",close:"~~",kind:"strike"},{open:"_",close:"_",kind:"italic",wordBoundary:!0},{open:"^^",close:"^^",kind:"quiet"},{open:"@@",close:"@@",kind:"highlight"},{open:"++",close:"++",kind:"bold"}],d=c.map(e=>e.style).filter(e=>u.some(t=>t.kind===e)),f=[...u,{open:"*",close:"*",kind:"accent"}],k=[...u,{open:"*",close:"*",kind:"accent"},{open:"#",close:"#",kind:"bold",notBefore:"0123456789"},{open:"[",close:"]",kind:"italic",notBefore:"("}];function p(e){return!/\s/.test(e)&&!/[!-\/:-@[-`{-~]/.test(e)}function g(e,t){const n=[];let l="",i=0;for(;i<e.length;){const r=m(e,i,t);r?(n.push({kind:"text",text:l}),l="",n.push({kind:r.rule.kind,text:r.inner}),i=r.end):(l+=e[i],i+=1)}return n.push({kind:"text",text:l}),n}function m(e,t,n){for(const l of n){if(!e.startsWith(l.open,t))continue;if(l.wordBoundary&&t>0&&p(e[t-1]))continue;const n=t+l.open.length,i=e.indexOf(l.close,n);if(i<n+1)continue;const r=e.slice(n,i);if(r.includes(l.close[0]))continue;if(r.includes("\n"))continue;const s=i+l.close.length,o=e[s];if((!l.notBefore||void 0===o||!l.notBefore.includes(o))&&(!l.wordBoundary||void 0===o||!p(o)))return{rule:l,inner:r,end:s}}return null}function x(e,t){return g(e,t).map(e=>e.text).join("")}var b=["http","https","mailto","tel"];function y(e){if(""===e||/[\s\u0000-\u001f\u007f]/.test(e))return!1;const t=/^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(e);return!t||b.includes(t[1].toLowerCase())}function S(e,t){if("["!==e[t])return null;const n=e.indexOf("]",t+1);if(n<t+2||"("!==e[n+1])return null;const l=e.slice(t+1,n);if(l.includes("["))return null;const i=e.indexOf(")",n+2);if(-1===i)return null;const r=e.slice(n+2,i);return y(r)?{label:l,href:r,end:i+1}:null}var v=2;function w(e,t,n){const l=[];let i="";const r=()=>{i&&l.push({kind:"text",text:i}),i=""},s=e=>n+1<v?w(e,t,n+1):[{kind:"text",text:e}];let o=0;for(;o<e.length;){const n=S(e,o);if(n){r(),l.push({kind:"link",href:n.href,children:s(n.label)}),o=n.end;continue}const c=m(e,o,t);c?(r(),l.push({kind:c.rule.kind,open:c.rule.open,close:c.rule.close,children:s(c.inner)}),o=c.end):(i+=e[o],o+=1)}return r(),l}function E(e,t){return e.split("\n").map(e=>{const n=e.startsWith("- ")&&""!==e.slice(2).trim();return{bullet:n,children:w(n?e.slice(2):e,t,0)}})}function B(e){return e.map(e=>"text"===e.kind?e.text:"link"===e.kind?`[${B(e.children)}](${e.href})`:e.open+B(e.children)+e.close).join("")}function q(e){return e.map(e=>(e.bullet?"- ":"")+B(e.children)).join("\n")}function O(t,n,l){if("link"===n)return void 0===l?null:{id:t,kind:"link",open:"[",close:`](${l})`,href:l};const i=e[n];return i&&"code"!==n?{id:t,kind:n,open:i.fence,close:i.fence}:null}function I(e,t){let n=0,l=0;return e.split("\n").map(e=>{const[i]=E(e,t);let r=l+(i.bullet?2:0);l+=e.length+1;const s=[],o=(e,t)=>{for(const l of e){if("text"===l.kind){for(const e of l.text)s.push({ch:e,marks:t,at:r}),r+=e.length;continue}const e="link"===l.kind?O(++n,"link",l.href):{id:++n,kind:l.kind,open:l.open,close:l.close};r+=e.open.length,o(l.children,[...t,e]),r+=e.close.length}};return o(i.children,[]),{bullet:i.bullet,chars:s}})}function $(e){let t="";const n=[];return e.forEach((e,l)=>{l>0&&(t+="\n"),e.bullet&&(t+="- ");const i=[],r=[];for(const n of e.chars){let e=0;for(;e<i.length&&e<n.marks.length&&i[e].id===n.marks[e].id;)e+=1;for(;i.length>e;)t+=i.pop().close;for(let l=e;l<n.marks.length;l+=1)t+=n.marks[l].open,i.push(n.marks[l]);r.push(t.length),t+=n.ch}for(;i.length>0;)t+=i.pop().close;n.push(r)}),{text:t,at:n}}function C(e,t){return e.length===t.length&&e.every((e,n)=>{const l=t[n];return e.bullet===l.bullet&&e.chars.length===l.chars.length&&e.chars.every((e,t)=>{const n=l.chars[t];return e.ch===n.ch&&e.marks.length===n.marks.length&&e.marks.every((e,t)=>e.kind===n.marks[t].kind&&e.href===n.marks[t].href)})})}function Q(e,t,n,l=u){const i=I(e,l),r=i.flatMap(e=>e.chars),s={text:e,selectionStart:t,selectionEnd:n},o=e=>i.map(t=>({bullet:t.bullet,chars:t.chars.map(t=>({...t,marks:t.marks.filter(n=>"link"===n.kind||!e(t,n))}))})),c=e=>{const t=$(e);return C(e,I(t.text,l))?t:null},a=(e,t)=>{let n=r.indexOf(t);for(let t=0;t<e.at.length;t+=1){if(n<e.at[t].length)return e.at[t][n];n-=e.at[t].length}return 0};if(t===n){const e=[...r].reverse().find(e=>e.at<t),n=r.find(e=>e.at>=t),l=new Set([...e?.marks??[],...n?.marks??[]].map(e=>e.id));if(![...l].some(e=>r.some(t=>t.marks.some(t=>t.id===e&&"link"!==t.kind))))return s;const i=c(o((e,t)=>l.has(t.id)));if(!i)return s;const h=n?a(i,n):e?a(i,e)+e.ch.length:0;return{text:i.text,selectionStart:h,selectionEnd:h}}const h=new Set(r.filter(e=>e.at>=t&&e.at<n));if(0===h.size)return s;const d=new Set([...h].flatMap(e=>e.marks.map(e=>e.id))),f=c(o(e=>h.has(e)))??c(o((e,t)=>d.has(t.id)));if(!f)return s;const k=r.find(e=>h.has(e)),p=[...r].reverse().find(e=>h.has(e));return{text:f.text,selectionStart:a(f,k),selectionEnd:a(f,p)+p.ch.length}}export{k as CAMPAIGN_MARKUP,d as COPY_FIELD_TOOLS,c as MARKUP_TOOLS,a as MARK_NAMES,t as MARK_PLACEHOLDERS,u as STANDARD_MARKUP,f as STOREFRONT_MARKUP,l as applyMark,Q as clearMarks,r as findLink,y as isSafeLinkHref,i as markedAt,I as markedLines,h as markupTools,E as parseMarkup,o as removeLink,C as sameMarks,q as serializeMarkup,O as spanFor,x as stripInline,g as tokenizeInline,s as writeLink,$ as writeMarkedLines};