@hazem3500/komo 0.9.24 → 0.9.25
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/chunk-G2QGDYNV.js +1 -0
- package/dist/chunk-K6ETEZER.js +1 -0
- package/dist/chunk-RPY7OOOR.js +1 -0
- package/dist/design-export-LA5VVR5Z.js +1 -0
- package/dist/design-export.d.ts +18 -0
- package/dist/design-mode-styles.d.ts +1 -1
- package/dist/design-mode.d.ts +14 -1
- package/dist/design-mode.js +1 -1
- package/dist/design-panel-KZCDP47N.js +1 -0
- package/dist/design-panel.d.ts +3 -2
- package/dist/design-target.d.ts +4 -0
- package/dist/design-tokens.d.ts +14 -13
- package/dist/index.js +1 -1
- package/dist/{inline-text-editor-Z2N32PER.js → inline-text-editor-JSJVHPMM.js} +1 -1
- package/dist/node.mjs +1 -1
- package/dist/react-props-panel-PV3SKNTA.js +1 -0
- package/dist/react-props-panel.d.ts +25 -24
- package/dist/react.js +1 -1
- package/dist/server.js +1 -1
- package/dist/setup.js +1 -1
- package/package.json +1 -1
- package/server/setup-client.txt +54 -64
- package/dist/chunk-AVMLHTCA.js +0 -1
- package/dist/chunk-JXIYWNFL.js +0 -1
- package/dist/design-export-YFMZGYR3.js +0 -1
- package/dist/design-panel-VLR2UILF.js +0 -1
- package/dist/react-props-panel-NC7KLZ73.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,d as t,e as n,g as o,h as i,i as r,j as a,k as s,l,m as d,n as p,o as c,p as u,q as f,r as g,s as m,t as h,u as b,v as k,w as v,x as y,y as x}from"./chunk-K6ETEZER.js";import"./chunk-RPY7OOOR.js";var w=new Map,E=new WeakMap,$=!1;function C(e){let t={};for(let n of e?.themes??[])try{t[n.id]=n.current()}catch{}return t}function S(e,t={}){let n=E.get(e);n||E.set(e,n=new Map);let o=JSON.stringify(Object.entries(t).sort()),i=n.get(o);return i||(i=Promise.resolve().then(()=>e.list(Object.keys(t).length?t:void 0)).then(e=>Array.isArray(e)?e.filter(e=>e&&"string"==typeof e.path):[]),i.catch(()=>n.delete(o)),n.set(o,i)),i}function P(e,t){return Promise.resolve().then(()=>e.resolve(t)).then(e=>e??{},()=>({}))}function A(e){let t,n=e.trim().toLowerCase().replace(/\s+/g," "),o=/^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/.exec(n)?.[1];if(o)t=(o.length<5?[...o].map(e=>e+e).join(""):o).match(/../g).map((e,t)=>parseInt(e,16)/(t>2?255:1));else{let e=/^rgba?\(([^)]*)\)$/.exec(n)?.[1].split(/\s*[,/]\s*|\s+/);e&&(3===e.length||4===e.length)&&e.every(e=>/^[\d.]+%?$/.test(e))&&(t=e.map((e,t)=>parseFloat(e)*(e.endsWith("%")?t>2?.01:2.55:1)))}if(!t)return n.replace(/\s*,\s*/g,",");let[i,r,a,s=1]=t.map((e,t)=>t>2?+e.toFixed(2):Math.round(e));return 1===s?`rgb(${i},${r},${a})`:`rgba(${i},${r},${a},${s})`}function N(e,t){let n=A(t);return n?e.find(e=>"string"==typeof e.value&&A(e.value)===n):void 0}function M(e){return e.label||e.path}function T(e){return[e.path,e.ref,e.value,e.states?.length?`States: ${e.states.join(", ")}`:"",e.description].filter(Boolean).join(" · ")}function L(){let e=document.createElement("span");return e.className="design-token-off",e.setAttribute("role","img"),e}function j(e,t,n){e.title=`Not from a token · ${t||"unset"}${n?` · matches ${M(n)}`:""}`,e.setAttribute("aria-label",e.title)}function z(e,t,n,o){try{if(e.preview)return e.preview(t,n,o)??(()=>{})}catch{return()=>{}}return function(e,t,n){let o=e.style;if(!o)return()=>{};let i=o.getPropertyValue(t),r=o.getPropertyPriority(t);return o.setProperty(t,n,r),()=>{i?o.setProperty(t,i,r):o.removeProperty(t)}}(t,n,o.value)}function O(e,t){return[...w.get(e)??[]].reverse().find(e=>e.property===t)?.token}function R(e){let t=w.get(e);t?.pop()?.undo(),t&&!t.length&&w.delete(e)}function D(e){return!!w.get(e)?.length}function q(e){for(;w.has(e);)R(e)}function V(e){return[...new Set(w.get(e)?.map(e=>e.property))]}function B(e,t){try{let n=t.adapter.describe?.(e,t.property,t.from,t.token);return n?String(n).replace(/\s+/g," ").replace(/→/g,"->").trim().slice(0,300):void 0}catch{return}}function U(e){let t=[],n=new Set;for(let o of function(e){let t=new Map;for(let n of w.get(e)??[])t.set(n.property,n);return[...t.values()].filter(e=>!("path"in e.from)||e.from.path!==e.token.path)}(e)){n.add(o.adapter.id);let i="path"in o.from?`${o.fromToken?.value?`${o.fromToken.value} `:""}[${o.from.path}]`:o.from.offToken||"(unset)";t.push(`Element ${o.property}: ${i} → ${o.token.value} [${o.token.path}]`);let r=B(e,o);r&&t.push(`Apply: ${r}`)}if(t.length)return["Proposed design-token changes (preview only)",...t,`Token adapter: ${[...n].join(", ")}`].join("\n")}var H=new Map,_=new Map,F=new WeakSet,I=new WeakMap;function W(e){return void 0===e?"unset":JSON.stringify(e)??"unset"}var Y=new Map;function J(e){if(e)for(let[e,n]of H){let o=t(e);o&&(Y.set(e,o.props),o.setProps({...o.props,...Object.fromEntries(n)}))}else for(let[e,n]of Y)t(e)?.setProps(n);e||Y.clear(),s(e),function(e){if(e!==$){$=e;for(let[t,n]of w)if(e)for(let e of[...n].reverse())e.undo();else for(let e of n)e.undo=z(e.adapter,t,e.property,e.token)}}(e)}function K(e){return!!H.get(e)?.size}function X(e){let n=t(e),o=n?.definition.textProp,i=n?.definition.props.find(e=>e.name===o);if(!n||!o||"string"!==i?.kind)return null;let r=n.props[o];if("string"!=typeof r||r.length>500)return null;let a=H.get(e);return a||H.set(e,a=new Map),a.has(o)||a.set(o,r),{propName:o,before:r}}function Z(n,o,i){let r=t(n),a=r?.definition.props.find(e=>e.name===o);return!(!r||r.definition.textProp!==o||"string"!==a?.kind||i.length>500||!e(a,i))&&(r.setProps({...r.props,[o]:i}),!0)}function G(e,t,n,o){if(n===o){let o=H.get(e);return void(o?.get(t)===n&&!(_.get(e)??[]).some(e=>e.propName===t)&&(o.delete(t),o.size||H.delete(e)))}let i=_.get(e);i||_.set(e,i=[]),i.push({propName:t,before:n,after:o})}function Q(e,t,n){Z(e,t,n);let o=H.get(e);o?.get(t)===n&&!(_.get(e)??[]).some(e=>e.propName===t)&&(o.delete(t),o.size||H.delete(e))}function ee(e){return!!e&&!!_.get(e)?.length}function te(e){let n=H.get(e),i=t(e);if(!n?.size||!i)return;let r=o(e),a=[...n].map(([e,t])=>{let n=i.definition.props.find(t=>t.name===e)?.styleProperty,o=i.props[e],a=n&&"string"==typeof o?r?.tokens.find(e=>e.properties.includes(n)&&o===`var(${e.cssVariable})`):void 0;return`- ${e}: ${W(t)} → ${W(o)}${a?` [${a.path}]`:" [custom value]"}`});return["Proposed React prop changes (preview only)",`Component: ${i.definition.name}`,`Source: ${i.definition.source}:${i.definition.line}`,...a,"Preview values use the app's React state callback; inline feedback does not write source files."].join("\n")}function ne(e,o){if(t(e))return null;let i;try{i=o?.components?.identify(e)}catch{}let r=n(e);return i?.name&&(!r||r.root!==i.element&&r.root.contains(i.element))?i:null}var oe=e=>String(e).replace(/\s+/g," ").trim();function ie(e,o){let i=Object.entries(C(o)).map(([e,t])=>`${oe(e)}=${oe(t)}`).join(", "),r=ne(e,o),a=t(e),s=a?{root:e,component:a}:r?void 0:n(e);if(s){let{definition:e,props:t}=s.component;r={name:e.name,source:`${e.source}:${e.line}`,props:{...t,...Object.fromEntries(H.get(s.root)??[])}}}let l=Object.entries(r?.props??{}).filter(([,e])=>null===e||["boolean","number"].includes(typeof e)||"string"==typeof e&&e.length<=80).slice(0,12).map(([e,t])=>`${oe(e)}=${JSON.stringify(t).replace(/→/g,"\\u2192")}`);return[i&&`Theme: ${i}`,r?.name&&`Component: ${oe(r.name)}${r.source?` (${oe(r.source)})`:""}`,l.length&&`Props: ${l.join(", ")}`].filter(e=>!!e)}function re(e){return[te(e),x(e),U(e)].filter(e=>!!e).join("\n\n")||void 0}function ae(e,n,o){I.get(e)?.abort();let i=new AbortController;I.set(e,i),e.addEventListener("click",e=>{let i=n();if(!i)return;let r=x(i)||D(i);!t(i)&&!r||(e.stopImmediatePropagation(),o(i,re(i)))},{capture:!0,signal:i.signal})}function se(e){return b(e)}function le(e){return h(e)||D(e)}function de(e){k(e)}function pe(e){v(e),q(e)}function ce(e){if(!e||F.has(e))return;let t=document.createElement("style");t.textContent=".design-react-source{display:block;padding:0 0 8px;color:#77736f;font-size:10px;overflow-wrap:anywhere}.design-react-inside{padding:10px 12px}.design-react-inside button{padding:0;border:0;background:none;color:#bda6ef;font:inherit;cursor:pointer}.design-react-inside button:hover{text-decoration:underline}.design-react-field.design-field{display:grid;grid-template-columns:76px minmax(0,1fr);gap:0 8px;height:auto;min-height:28px;margin-top:4px;background:none;box-shadow:none;color:#898680;font-size:11px}.design-react-field>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.design-react-field.design-field>:is(input,select){box-sizing:border-box;width:100%;min-width:0;height:28px;padding:0 8px;border:0;border-radius:6px;background-color:#ffffff0a;color:#f1efeb;font:inherit;font-size:11px}.design-react-field.design-field>:is(input,select):focus-visible{outline:1px solid #bda6ef;outline-offset:-1px}.design-react-field.design-field>select{padding-right:20px}.design-react-field input[type=checkbox]{justify-self:end;width:14px;height:14px;accent-color:#bda6ef}.design-react-field input:disabled{opacity:.55;cursor:not-allowed}.design-react-type{display:none}.design-react-field .design-token-binding{grid-column:2;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:6px;margin-top:4px;color:#77736f;font-size:10px}.design-react-field .design-token-binding select{min-width:0;height:24px;border:0;border-radius:6px;appearance:none;background:#ffffff0a url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 3 4 5.5 6.5 3' fill='none' stroke='%23898680' stroke-width='1.2'/%3E%3C/svg%3E\") right 6px center/8px no-repeat;color:#e9e6e1;padding:0 18px 0 6px;font:inherit;font-size:10px;cursor:pointer}.design-react-field .design-token-binding[data-mode=token] select{background-color:#bda6ef24;color:#e6dcfb}.design-token-binding__state{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.design-field>.design-token-binding{display:contents}.design-field:has(>.design-token-binding)>input[data-property]{padding-right:28px}.design-token-icon,.design-token-detach,.design-field>.design-token-binding select{position:absolute;top:4px;right:4px;width:20px;height:20px;box-sizing:border-box;border-radius:5px}.design-token-icon{display:grid;place-items:center;color:#77736f;opacity:0;pointer-events:none;transition:opacity .12s}.design-token-icon::before{content:'';width:6px;height:6px;border:1.2px solid currentColor;border-radius:1.5px;rotate:45deg}.design-field:is(:hover,:focus-within) .design-token-icon{opacity:1}.design-field>.design-token-binding select{margin:0;padding:0;border:0;opacity:0;cursor:pointer;appearance:none}.design-field>.design-token-binding select:hover+.design-token-icon,.design-field:has(.design-token-binding select:hover) .design-token-icon{background:#ffffff14;color:#e9e6e1}.design-field:has(.design-token-binding select:focus-visible) :is(.design-token-icon,.design-token-chip){outline:2px solid #bda6ef;outline-offset:1px;opacity:1}.design-field[data-token-mode=override] .design-token-icon{opacity:1;color:#e7c27d}.design-token-chip,.design-token-detach{display:none}.design-field:is([data-token-mode=token],[data-token-mode=connected])>[data-property]{visibility:hidden}.design-field:is([data-token-mode=token],[data-token-mode=connected]) .design-token-chip{position:absolute;inset:4px 28px 4px var(--lead,4px);display:flex;align-items:center;gap:5px;padding:0 6px;border-radius:4px;background:#bda6ef1f;color:#e6dcfb;font-size:11px;white-space:nowrap;overflow:hidden;pointer-events:none}.design-token-chip::before{content:'';flex:none;width:5px;height:5px;border:1.2px solid #c8b5f4;border-radius:1px;rotate:45deg}.design-field:is([data-token-mode=token],[data-token-mode=connected]) .design-token-binding select{left:var(--lead,4px);right:28px;width:auto}.design-field:is([data-token-mode=token],[data-token-mode=connected]) .design-token-icon{display:none}.design-field:is([data-token-mode=token],[data-token-mode=connected]) .design-token-detach{display:grid;place-items:center;color:#898680}.design-token-detach:hover{background:#ffffff14;color:#f1efeb}.design-token-detach svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round}.design-theme-group .design-react-source{padding:0 0 6px}.design-theme-heading{display:block;padding:8px 0 2px;color:#77736f;font-size:10px;text-transform:capitalize}.design-theme-token{position:relative;display:grid;grid-template-columns:96px minmax(0,1fr) 20px;align-items:center;gap:6px;margin-top:4px}.design-theme-token>span{overflow:hidden;color:#898680;font-size:11px;text-overflow:ellipsis;white-space:nowrap}.design-theme-token[data-changed]>span{color:#e6dcfb}.design-theme-token[data-changed]::before{content:'';position:absolute;top:calc(50% - 2px);left:-8px;width:4px;height:4px;border-radius:50%;background:#bda6ef}.design-theme-reset{display:grid;place-items:center;width:20px;height:20px;padding:0;border:0;border-radius:5px;background:none;color:#77736f;cursor:pointer}.design-theme-reset:disabled{visibility:hidden}.design-theme-reset:hover{background:#ffffff14;color:#f1efeb}.design-theme-reset svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}.design-token-off{position:absolute;top:8px;right:24px;display:grid;place-items:center;width:12px;height:12px}.design-token-off::before{content:'';width:4px;height:4px;border-radius:50%;background:#e7c27d;opacity:.7}.design-token-off[hidden]{display:none}.design-field:has(>.design-token-binding>.design-token-off:not([hidden]))>input[data-property]{padding-right:38px}.design-theme-switch{padding:6px 12px 8px}.design-theme-switch .design-react-field>span{text-transform:capitalize}.design-theme-options{display:flex;min-width:0;padding:2px;border-radius:6px;background:#ffffff0a}.design-theme-options button{flex:1;min-width:0;height:24px;padding:0 6px;border:0;border-radius:4px;background:none;color:#898680;font:inherit;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.design-theme-options button:hover{color:#f1efeb}.design-theme-options button[aria-pressed=true]{background:#ffffff1a;color:#f1efeb}.design-theme-options button:focus-visible{outline:1px solid #bda6ef;outline-offset:-1px}@media (max-width:520px){.design-theme-options button{height:30px}.design-react-field.design-field>:is(input,select){height:34px}.design-token-icon,.design-token-detach,.design-field>.design-token-binding select{top:7px}.design-token-off{top:11px}}.design-token-match{grid-column:1/-1;display:flex;align-items:center;gap:6px;min-width:0;margin-top:-2px;padding:0 4px;color:#77736f;font-size:10px}.design-token-match[hidden]{display:none}.design-token-match>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.design-token-match button{flex:none;padding:0;border:0;background:none;color:#bda6ef;font:inherit;cursor:pointer}.design-token-match button:hover{text-decoration:underline}.design-token-match button:focus-visible{outline:1px solid #bda6ef;outline-offset:2px;border-radius:2px}@media (pointer:coarse){.design-token-match button{min-height:32px}}",e.append(t),F.add(e)}function ue(e,t){e.dataset.picker="token",e.setAttribute("aria-haspopup","listbox"),e.setAttribute("aria-expanded","false");let n,o=n=>import("./token-picker-XXX4L3Y7.js").then(o=>{!e.isConnected||e.disabled||!n&&o.isTokenPickerOpen(e)||o.toggleTokenPicker({trigger:e,...t()})},()=>{});e.addEventListener("pointerdown",t=>{t.button||(t.preventDefault(),n="mouse"===t.pointerType?void 0:t,!n&&(e.focus(),o(!0)))}),e.addEventListener("pointerup",e=>{n&&Math.abs(e.clientY-n.clientY)<=10&&o(!0),n=void 0});for(let t of["mousedown","touchend"])e.addEventListener(t,e=>{e.cancelable&&e.preventDefault()});e.addEventListener("keydown",e=>{e.ctrlKey||e.metaKey||!["Enter"," ","ArrowDown","ArrowUp"].includes(e.key)||(e.preventDefault(),o(!1))})}function fe(e,t){let n=document.createElement("div");n.className="design-token-match",n.hidden=!0;let o=document.createElement("span"),i=document.createElement("button");i.type="button",i.textContent="Use token",n.append(o,i);let r=()=>{};return i.addEventListener("click",e=>{e.preventDefault(),r()}),{show(a,s){n.isConnected||(e??t.parentElement)?.after(n),n.hidden=!a,r=s,o.textContent=a?`Matches ${a.label||a.path}`:"",o.title=a?`${a.path}${a.ref?` · ${a.ref}`:""} · ${a.value}`:"",i.setAttribute("aria-label",a?`Use token ${a.label||a.path}`:"Use token")}}}function ge(e,t,n,r){let a=o(e);if(!a)return null;let s=m(a,t);if(!s.length)return null;ce(r);let l=document.createElement("span");l.className="design-token-binding",l.setAttribute("data-mode","custom");let c=document.createElement("span");c.className="design-token-icon",c.setAttribute("aria-hidden","true");let h=document.createElement("span");h.className="design-token-chip",h.setAttribute("aria-hidden","true");let b=document.createElement("button");b.type="button",b.className="design-token-detach",b.title="Detach token",b.setAttribute("aria-label",`Detach token from ${t}`),b.innerHTML='<svg viewBox="0 0 12 12"><path d="M5 3.5 6.5 2a2.1 2.1 0 0 1 3 3L8 6.5M7 8.5 5.5 10a2.1 2.1 0 0 1-3-3L4 5.5M2 2l8 8"/></svg>';let k=document.createElement("select");k.setAttribute("aria-label",`Style token for ${t}`);let v=document.createElement("small");v.className="design-token-binding__state",v.setAttribute("aria-live","polite");let y=`komo-token-${t}-${Math.random().toString(36).slice(2,8)}`;v.id=y,k.setAttribute("aria-describedby",y);let x=document.createElement("option");x.value="custom",x.textContent="Custom value",k.append(x);for(let e of s){let t=document.createElement("option"),n=i(a,e);t.value=e.path,t.textContent=n?`${e.path} · ${n}`:e.path,k.append(t)}let w=L(),E=e=>({path:e.path,type:e.type,value:i(a,e),properties:e.properties,group:e.path.split(".")[0],ref:e.cssVariable}),$=fe(null,l),C=e=>{k.value=e,k.dispatchEvent(new Event("change"))};ue(k,()=>({tokens:s.map(E),property:t,current:k.value,onSelect:e=>C(e.path)}));let S=()=>{let n=u(a,e,t),o=n?null:f(a,e,t),i="token"===n?.mode?s.find(e=>e.path===n.tokenPath):void 0,r=i??o?.token;k.value=r?.path??"custom",h.textContent=r?.path??"";let d=n?.declaredPath,p=i?"token":o?"connected":d?"override":"custom";l.dataset.mode=p,l.parentElement?.setAttribute("data-token-mode",p),v.textContent="token"===p?d&&d!==i?.path?`Rebound from ${d} · preview`:`Linked to ${i?.path} · preview`:"connected"===p?"Connected "+("inline"===o?.origin?"inline":"from stylesheet"):"override"===p?`Custom override · was ${d}`:"",k.title=v.textContent||"Choose a token",w.hidden="custom"!==p;let c="custom"===p?getComputedStyle(e).getPropertyValue(t).trim():"",g="custom"===p?N(s.map(E),c):void 0;"custom"===p&&j(w,c,g),$.show(g,()=>g&&C(g.path))},P=new MutationObserver(S);P.observe(e,{attributes:!0,attributeFilter:["style"]});let A=new MutationObserver(()=>{l.isConnected||(P.disconnect(),A.disconnect())});return A.observe(l.ownerDocument,{childList:!0,subtree:!0}),k.addEventListener("change",()=>{let o=e.style.getPropertyValue(t),i=s.find(e=>e.path===k.value),r=u(a,e,t);if(i&&r&&i.path===r.declaredPath)g(a,e,t),n(o,e.style.getPropertyValue(t),i.path);else if(i)(i.path!==f(a,e,t)?.token.path||r)&&d(a,e,i,t,{recordHistory:!1})&&n(o,e.style.getPropertyValue(t),i.path);else{let i=l.parentElement?.querySelector("[data-property]")?.value??getComputedStyle(e).getPropertyValue(t).trim(),r=/^-?[\d.]+$/.test(i.trim())&&!/weight|line/.test(t)?`${i.trim()}px`:i;p(a,e,t,r),e.style.setProperty(t,r),n(o,r)}S()}),b.addEventListener("click",()=>{let e=s.find(e=>e.path===k.value),t=l.parentElement?.querySelector("input[data-property]"),n=e&&i(a,e);t&&n&&(t.value="number"===t.type?String(parseFloat(n)):n),k.value="custom",k.dispatchEvent(new Event("change")),l.parentElement?.querySelector("[data-property]")?.focus()}),l.append(h,k,c,b,w,v),queueMicrotask(S),S(),l}function me(e){let t=o(e);return new Set([...t?.elementBindings.get(e)?.keys()??[],...V(e)])}function he(e,t,n,o,i,r,a,s,l){let d=t.flatMap(e=>{let t=[...n.querySelectorAll("[data-field-property]")].find(t=>t.dataset.fieldProperty===e.property),o=t?.querySelector("[data-property]");return t&&o?[{field:e,label:t,input:o}]:[]}),p=t=>{for(let{field:o,label:i,input:s}of d){if(i.querySelector(".design-token-binding")||!n.contains(i))continue;let l=t(o,i,s,()=>{r&&(s.value=r(o,e));let t=i.querySelector('input[type="range"],input[type="color"]');t&&(t.value="color"===o.kind&&a?a(s.value):s.value)});l&&i.append(l)}},c=s?.tokens;if(!c)return void p((t,n,r,a)=>ge(e,t.property,e=>{o(t,r,e),a()},i));ce(i);let u=function(e,t){let n,o=(Array.isArray(t?.themes)?t.themes:[]).find(e=>Array.isArray(e?.options)&&e.options.length>1&&e.options.length<4);if(o)return()=>n??=Promise.all(o.options.map(n=>S(e,{...C(t),[o.id]:n.id}).then(e=>({label:Ne(n.label,n.id),values:new Map(e.map(e=>[e.path,e.value]))})))).catch(()=>[])}(c,s);return Promise.all([S(c,C(s)),P(c,e)]).then(([t,n])=>{p((o,i,r,a)=>be(c,e,o.property,t,n[o.property],e=>{l?.(e),a()},i,r,u))},()=>{})}function be(e,t,n,o,i,r,a,s,l){let d=function(e,t){return e.filter(e=>e.properties?.includes(t))}(o,n);if(!d.length&&!i)return null;let p=i&&"offToken"in i?i.offToken:void 0,c=void 0===p?void 0:N(d,p),u=document.createElement("span");u.className="design-token-binding";let f=document.createElement("span");f.className="design-token-chip",f.setAttribute("aria-hidden","true");let g=document.createElement("span");g.className="design-token-icon",g.setAttribute("aria-hidden","true");let m=document.createElement("button");m.type="button",m.className="design-token-detach",m.title="Edit the value",m.setAttribute("aria-label",`Edit ${n} value`),m.innerHTML='<svg viewBox="0 0 12 12"><path d="M5 3.5 6.5 2a2.1 2.1 0 0 1 3 3L8 6.5M7 8.5 5.5 10a2.1 2.1 0 0 1-3-3L4 5.5M2 2l8 8"/></svg>';let h=document.createElement("select");h.setAttribute("aria-label",`Style token for ${n}`),h.disabled=!d.length;let b=document.createElement("option");b.value="",b.textContent="Choose a token",h.append(b);let k=new Map([["",h]]);for(let e of d){let t=e.group??"",n=k.get(t);n||(n=document.createElement("optgroup"),n.label=t,k.set(t,n));let o=document.createElement("option");o.value=e.path,o.textContent=`${M(e)}${e.ref?` · ${e.ref}`:""}${e===c?" · same value":""}`,o.title=T(e),n.append(o)}for(let[e,t]of k)e&&h.append(t);let v=L();void 0!==p&&j(v,p,c);let y=document.createElement("small");y.className="design-token-binding__state",y.setAttribute("aria-live","polite");let x=!1,E=fe(a,u);ue(h,()=>({tokens:o,property:n,current:x?void 0:O(t,n)?.path??(i&&"path"in i?i.path:void 0),themes:l,onSelect:C}));let $=()=>{let e=O(t,n),r=x?void 0:e?.path??(i&&"path"in i?i.path:void 0),s=r?o.find(e=>e.path===r):void 0;h.value=r&&d.some(e=>e.path===r)?r:"",f.textContent=s?M(s):r??"";let l=r?e?"token":"connected":"custom";u.dataset.mode=l,(a??u.parentElement)?.setAttribute("data-token-mode",l),v.hidden=void 0===p||!!e,y.textContent=s?`${e?"Preview":"Uses"} ${T(s)}`:r?`Uses ${r}`:v.hidden?"":v.title,h.title=y.textContent||"Choose a token",E.show(v.hidden||x?void 0:c,()=>c&&C(c))};function C(a){x=!1;let s=i??{offToken:getComputedStyle(t).getPropertyValue(n).trim()},l="path"in s?o.find(e=>e.path===s.path):void 0;r(function(e,t,n,o,i,r){let a=w.get(t);a||w.set(t,a=[]);let s=a.find(e=>e.property===n);return a.push({adapter:e,property:n,token:o,from:s?.from??i,fromToken:s?s.fromToken:r,undo:z(e,t,n,o)}),()=>R(t)}(e,t,n,a,s,l)),$()}return h.addEventListener("change",()=>{let e=d.find(e=>e.path===h.value);e?C(e):$()}),m.addEventListener("click",()=>{x=!0,$(),s?.focus()}),u.append(f,h,g,m,v,y),$(),u}var ke=!1;function ve(e,t,n,i){let r=o(e);if(!r||!r.tokens.length)return null;ce(i);let a=document.createElement("details");a.className="design-group design-theme-group",a.open=ke,a.addEventListener("toggle",()=>{a.isConnected&&(ke=a.open)});let s=document.createElement("summary");s.textContent="Shared theme";let l=document.createElement("small");l.className="design-react-source",l.textContent="Changes every element using these tokens",a.append(s,l);let d=new Map;for(let e of r.tokens){let t=e.path.split(".")[0];d.set(t,[...d.get(t)??[],e])}let p=r.tokens.length>6&&d.size>1;for(let[e,o]of p?d:new Map([["",r.tokens]])){if(e){let t=document.createElement("small");t.className="design-theme-heading",t.textContent=e,a.append(t)}for(let i of o)a.append(ye(r,i,t,n,e))}return a}function ye(e,t,n,o,s){let d=document.createElement("div");d.className="design-theme-token";let p=document.createElement("span");p.textContent=s&&t.path.slice(s.length+1)||t.path,p.title=`${t.path} · ${r(e,t)} matching · ${t.impactSelector}`;let c=n.fields.find(e=>t.properties.includes(e.property)),u={property:t.cssVariable,label:`Shared theme value for ${t.path}`,kind:"dimension"===t.type?"size":c?.kind??"text",glyph:"color"===t.type?void 0:c?.glyph,values:c?.values},f=!1,g=n.fieldControl(u,{element:e.root,begin:()=>{f=!1},apply:(n,i,r)=>{let s=null!==r&&a(e,t,r.trim(),f);n.setAttribute("aria-invalid",String(!s)),s&&(f=!0,k(),o())},commit:(e,t,n)=>{!1!==n&&(f=!1,"true"===e.getAttribute("aria-invalid")&&b())}}),m=g.querySelector("[data-property]"),h=g.querySelector('input[type="color"]'),b=()=>{let o=i(e,t);m.value=o,h&&(h.value=n.toHex(o)),m.removeAttribute("aria-invalid"),k()},k=()=>{v.disabled=!d.toggleAttribute("data-changed",e.themeEdits.has(t.path)),"fontFamily"===t.type&&(m.title=m.value)},v=document.createElement("button");return v.type="button",v.className="design-theme-reset",v.title="Reset to page value",v.setAttribute("aria-label",`Reset ${t.path}`),v.innerHTML='<svg viewBox="0 0 16 16"><path d="M2.5 2.5v3h3M3 5.5a5.5 5.5 0 1 1-.5 2.5"/></svg>',v.addEventListener("click",()=>{l(e,t),b(),o()}),b(),d.append(p,g,v),d}function xe(e,t,n){let i=o(e);i&&p(i,e,t,n)}function we(e,t){let n=o(e);n&&c(n,e,t)}function Ee(e){let n=_.get(e)?.pop(),o=t(e);if(!n||!o)return;o.setProps({...o.props,[n.propName]:n.before});let i=H.get(e);if(i){let t=i.get(n.propName);Object.is(t,n.before)&&i.delete(n.propName),i.size||H.delete(e)}}function $e(){for(let e of[...H.keys()])Te(e);H.clear(),_.clear(),y(),function(){for(let e of[...w.keys()])q(e)}(),Ae()}var Ce,Se=new Map;function Pe(e){try{return String(e.current())}catch{return}}function Ae(){for(let[e,t]of Se)try{Pe(e)!==t&&e.apply(t)}catch{}Se.clear()}var Ne=(e,t)=>e||t.charAt(0).toUpperCase()+t.slice(1);function Me(e,t,n,o){if(e.querySelector(".design-theme-switch"))return;let i=document.createElement("div");i.className="design-group design-theme-switch";let r,a=t?.themes;for(let e of Array.isArray(a)?a:[]){let t=Pe(e),o=Array.isArray(e?.options)?e.options.filter(e=>"string"==typeof e?.id):[];if(void 0===t||o.length<2)continue;let a=Ne(e.label,String(e.id)),s=o=>{let i=Pe(e);if(o!==i){Se.has(e)||Se.set(e,i??t),Ce=e;try{e.apply(o)}catch{}n()}},l=document.createElement(o.length>3?"label":"div");l.className="design-field design-react-field";let d,p=document.createElement("span");if(p.textContent=a,o.length>3){let e=document.createElement("select");for(let t of o)e.append(new Option(Ne(t.label,t.id),t.id));e.value=t,e.setAttribute("aria-label",`${a} theme`),e.addEventListener("change",()=>s(e.value)),d=e}else{d=document.createElement("div"),d.className="design-theme-options",d.setAttribute("role","group"),d.setAttribute("aria-label",`${a} theme`);for(let e of o){let n=document.createElement("button");n.type="button",n.textContent=Ne(e.label,e.id),n.setAttribute("aria-pressed",String(e.id===t)),n.addEventListener("click",()=>s(e.id)),d.append(n)}}Ce===e&&(r=d.querySelector("[aria-pressed=true]")??d),l.append(p,d),i.append(l)}Ce=void 0,i.childElementCount&&(ce(o),e.prepend(i),r?.focus({preventScroll:!0}))}function Te(e){let n=H.get(e),o=t(e);!n?.size||!o||(o.setProps({...o.props,...Object.fromEntries(n)}),H.delete(e),_.delete(e))}function Le(t,n,o,i,r,a){let s=n.definition.props.find(e=>e.name===o);if(!s||!e(s,i))return r.setAttribute("aria-invalid","true"),!1;r.removeAttribute("aria-invalid");let l=n.props[o];if(Object.is(l,i))return!0;let d=H.get(t);d||H.set(t,d=new Map);let p=d.has(o)?d.get(o):l;Object.is(p,i)?d.delete(o):d.set(o,p),d.size||H.delete(t);let c=_.get(t);return c||_.set(t,c=[]),c.push({propName:o,before:l,after:i}),n.setProps({...n.props,[o]:i}),a(),!0}function je(e,i,r,a,s){let l=t(e);if(!l){let t=ne(e,s),o=null;try{o=t&&s?.components?.panel?.(t)||null}catch{}return o&&ce(r),o??function(e,t,o){let i=n(e);if(!i)return null;ce(o);let r=document.createElement("small");if(r.className="design-react-source design-react-group design-react-inside",r.append(`Inside ${i.component.definition.name}`),t){let e=document.createElement("button");e.type="button",e.textContent="Select component",e.addEventListener("click",()=>t(i.root)),r.append(" · ",e)}return r}(e,a,r)}ce(r);let d=document.createElement("details");d.className="design-group design-react-group",d.open=!0;let p=document.createElement("summary");p.textContent="Properties",d.append(p);let c=document.createElement("small");c.className="design-react-source",c.textContent=`${l.definition.name} · ${l.definition.source}:${l.definition.line}`,d.append(c);for(let t of l.definition.props){let n=t.styleProperty,r=document.createElement("label");r.className="design-field design-react-field";let a=document.createElement("span");a.textContent=t.name;let s,p=l.props[t.name];if("enum"===t.kind){let e=document.createElement("select");for(let n of t.values??[]){let t=document.createElement("option");t.value=String(n),t.textContent=String(n),e.append(t)}if(void 0===p&&!t.required){let t=document.createElement("option");t.value="",t.textContent="unset",e.prepend(t)}e.value=void 0===p?"":String(p),s=e}else{let e=document.createElement("input");"boolean"===t.kind?(e.type="checkbox",e.checked=!0===p):"number"===t.kind?(e.type="number",e.step="any",e.value="number"==typeof p?String(p):""):(e.type="text",e.maxLength=500,e.autocomplete="off",e.value="string"==typeof p?p:""),s=e}if(s.setAttribute("aria-label",`${l.definition.name} ${t.name}`),"unsupported"===t.kind)s=document.createElement("input"),s.disabled=!0,s.value=`Read only · ${t.typeLabel}`,s.setAttribute("aria-label",`${l.definition.name} ${t.name}, read only`),r.title=`Inline feedback does not edit ${t.typeLabel} props.`;else{let n=()=>{let n=s instanceof HTMLInputElement&&"checkbox"===s.type?s.checked:s.value,o=n;if("number"===t.kind)o=""===String(n).trim()?void 0:Number(n);else if("enum"===t.kind){let e=(t.values??[]).find(e=>String(e)===n);o=""!==n||t.required?e:void 0}else"boolean"===t.kind&&(o=!0===n);Le(e,l,t.name,o,s,i)};s.addEventListener("change",n)}r.append(a,s);let c=document.createElement("small");if(c.className="design-react-type",c.textContent=`${t.typeLabel}${t.required?" · required":" · optional"}`,r.append(c),r.title||=c.textContent,"string"===t.kind&&n){let a=o(e),d=a?m(a,n):[];if(d.length){let o=document.createElement("span");o.className="design-token-binding";let a=document.createElement("span");a.textContent="Style token";let p=document.createElement("select");p.setAttribute("aria-label",`Style token for ${t.name}`);let c=document.createElement("option");c.value="custom",c.textContent="Custom value",p.append(c);for(let e of d){let t=document.createElement("option");t.value=e.path,t.textContent=e.path,p.append(t)}let u=()=>{let e=d.find(e=>l.props[t.name]===`var(${e.cssVariable})`);p.value=e?.path??"custom",o.dataset.mode=e?"token":"custom"};p.addEventListener("change",()=>{let o=d.find(e=>e.path===p.value),r=o?`var(${o.cssVariable})`:"string"==typeof l.props[t.name]&&String(l.props[t.name]).startsWith("var(")?e.ownerDocument.defaultView?.getComputedStyle(e).getPropertyValue(n).trim()??"":"string"==typeof l.props[t.name]?l.props[t.name]:"";Le(e,l,t.name,r,s,i)&&u()}),o.append(a,p),r.append(o),u()}}d.append(r)}return d}export{he as attachStyleTokenControls,Me as attachThemeSwitcher,X as beginReactTextEdit,se as canUndoDesignTokenEdit,ee as canUndoReactProp,Q as cancelReactTextEdit,be as createAdapterTokenControl,ve as createDesignThemePanel,ge as createElementTokenControl,je as createReactPropsPanel,ie as designContext,G as finishReactTextEdit,le as hasDesignTokenEdit,K as hasReactPropChanges,ae as installCommentCapture,xe as noteDesignTokenOverride,Z as previewReactTextEdit,re as proposedDesignChanges,te as proposedReactChanges,pe as resetDesignTokenEdits,$e as resetPreviews,Te as resetReactProps,Ae as restoreThemes,J as showDesignBefore,we as syncDesignTokenBinding,me as tokenBoundProperties,de as undoDesignTokenEdit,Ee as undoReactProp};
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
+
import type { DesignTarget } from "./design-target.js";
|
|
1
2
|
import type { DesignSystem, DesignToken, TokenAdapter, TokenUsage } from "./design-system.js";
|
|
2
3
|
import type { ThemeValues } from "./token-picker.js";
|
|
3
4
|
/** Before/After for React prop previews and shared theme values. */
|
|
4
5
|
export declare function showDesignBefore(on: boolean): void;
|
|
5
|
-
export declare function hasReactPropChanges(element:
|
|
6
|
+
export declare function hasReactPropChanges(element: DesignTarget): boolean;
|
|
6
7
|
export interface ReactTextEditStart {
|
|
7
8
|
propName: string;
|
|
8
9
|
before: string;
|
|
9
10
|
}
|
|
10
11
|
/** Only an explicit registered textProp can drive a React-rendered inline edit. */
|
|
11
|
-
export declare function beginReactTextEdit(element:
|
|
12
|
+
export declare function beginReactTextEdit(element: DesignTarget): ReactTextEditStart | null;
|
|
12
13
|
/** Preview through the registered React state callback; never mutate React's DOM. */
|
|
13
|
-
export declare function previewReactTextEdit(element:
|
|
14
|
-
export declare function finishReactTextEdit(element:
|
|
15
|
-
export declare function cancelReactTextEdit(element:
|
|
16
|
-
export declare function canUndoReactProp(element:
|
|
17
|
-
export declare function proposedReactChanges(element:
|
|
14
|
+
export declare function previewReactTextEdit(element: DesignTarget, propName: string, value: string): boolean;
|
|
15
|
+
export declare function finishReactTextEdit(element: DesignTarget, propName: string, before: string, after: string): void;
|
|
16
|
+
export declare function cancelReactTextEdit(element: DesignTarget, propName: string, before: string): void;
|
|
17
|
+
export declare function canUndoReactProp(element: DesignTarget | null): boolean;
|
|
18
|
+
export declare function proposedReactChanges(element: DesignTarget): string | undefined;
|
|
18
19
|
/**
|
|
19
20
|
* Context lines for a proposal, so agents and the CLI know what the change was
|
|
20
21
|
* made in: "Theme: mode=dark", "Component: PromoCard (src/card.tsx:19)" and
|
|
21
22
|
* 'Props: tone="calm"'. The registered React component wins, then the app's
|
|
22
23
|
* component adapter, then the registered component around the element.
|
|
23
24
|
*/
|
|
24
|
-
export declare function designContext(element:
|
|
25
|
-
export declare function proposedDesignChanges(element:
|
|
26
|
-
export declare function installCommentCapture(button: HTMLButtonElement, selected: () =>
|
|
27
|
-
export declare function canUndoDesignTokenEdit(element:
|
|
28
|
-
export declare function hasDesignTokenEdit(element:
|
|
29
|
-
export declare function undoDesignTokenEdit(element:
|
|
30
|
-
export declare function resetDesignTokenEdits(element:
|
|
25
|
+
export declare function designContext(element: DesignTarget, design?: DesignSystem): string[];
|
|
26
|
+
export declare function proposedDesignChanges(element: DesignTarget): string | undefined;
|
|
27
|
+
export declare function installCommentCapture(button: HTMLButtonElement, selected: () => DesignTarget | null, onComment: (element: Element, proposal?: string) => void): void;
|
|
28
|
+
export declare function canUndoDesignTokenEdit(element: DesignTarget | null): boolean;
|
|
29
|
+
export declare function hasDesignTokenEdit(element: DesignTarget): boolean;
|
|
30
|
+
export declare function undoDesignTokenEdit(element: DesignTarget): void;
|
|
31
|
+
export declare function resetDesignTokenEdits(element: DesignTarget): void;
|
|
31
32
|
/** Add token references directly to the existing style-property row. */
|
|
32
|
-
export declare function createElementTokenControl(element:
|
|
33
|
+
export declare function createElementTokenControl(element: DesignTarget, property: string, onEdit: (before: string, after: string, tokenPath?: string) => void, styleRoot?: ShadowRoot): HTMLElement | null;
|
|
33
34
|
/** Properties whose before/after is described by token provenance instead of raw CSS. */
|
|
34
|
-
export declare function tokenBoundProperties(element:
|
|
35
|
+
export declare function tokenBoundProperties(element: DesignTarget): Set<string>;
|
|
35
36
|
export declare function attachStyleTokenControls<T extends {
|
|
36
37
|
property: string;
|
|
37
38
|
kind?: string;
|
|
38
|
-
}>(element:
|
|
39
|
+
}>(element: DesignTarget, fields: readonly T[], container: HTMLElement, onEdit: (field: T, input: HTMLInputElement | HTMLSelectElement, before: string) => void, styleRoot?: ShadowRoot, valueFor?: (field: T, element: DesignTarget) => string, toHex?: (value: string) => string, design?: DesignSystem, onSwap?: (undo: () => void) => void): void | Promise<void>;
|
|
39
40
|
/** A field's token chip, suggestions and off-token marker, driven by the app's adapter. */
|
|
40
|
-
export declare function createAdapterTokenControl(adapter: TokenAdapter, element:
|
|
41
|
+
export declare function createAdapterTokenControl(adapter: TokenAdapter, element: DesignTarget, property: string, tokens: readonly DesignToken[], usage: TokenUsage | undefined, onSwap: (undo: () => void) => void, label?: HTMLElement, input?: HTMLElement, themes?: () => Promise<ThemeValues[]>): HTMLElement | null;
|
|
41
42
|
type ThemeFields = Pick<typeof import("./design-panel.js"), "fieldControl" | "fields" | "toHex">;
|
|
42
43
|
/**
|
|
43
44
|
* Shared theme editing stays secondary; per-element token choice lives on each knob.
|
|
44
45
|
* Token rows reuse the panel's own fields and preview live, like every other field.
|
|
45
46
|
*/
|
|
46
|
-
export declare function createDesignThemePanel(element:
|
|
47
|
-
export declare function noteDesignTokenOverride(element:
|
|
48
|
-
export declare function syncDesignTokenBinding(element:
|
|
49
|
-
export declare function undoReactProp(element:
|
|
47
|
+
export declare function createDesignThemePanel(element: DesignTarget, panel: ThemeFields, onEdit: () => void, styleRoot?: ShadowRoot): HTMLElement | null;
|
|
48
|
+
export declare function noteDesignTokenOverride(element: DesignTarget, property: string, value: string): void;
|
|
49
|
+
export declare function syncDesignTokenBinding(element: DesignTarget, property: string): void;
|
|
50
|
+
export declare function undoReactProp(element: DesignTarget): void;
|
|
50
51
|
/** Undo every prop, token and theme preview, and put switched themes back, e.g. when Design mode closes. */
|
|
51
52
|
export declare function resetPreviews(): void;
|
|
52
53
|
/** Put every axis Design mode switched back to its original option. */
|
|
@@ -59,6 +60,6 @@ export declare function restoreThemes(): void;
|
|
|
59
60
|
* so token lists, chips and values follow the new theme.
|
|
60
61
|
*/
|
|
61
62
|
export declare function attachThemeSwitcher(container: HTMLElement, design: DesignSystem | undefined, onSwitch: () => void, styleRoot?: ShadowRoot): void;
|
|
62
|
-
export declare function resetReactProps(element:
|
|
63
|
-
export declare function createReactPropsPanel(element:
|
|
63
|
+
export declare function resetReactProps(element: DesignTarget): void;
|
|
64
|
+
export declare function createReactPropsPanel(element: DesignTarget, onEdit: () => void, styleRoot?: ShadowRoot, select?: (root: HTMLElement) => void, design?: DesignSystem): HTMLElement | null;
|
|
64
65
|
export {};
|
package/dist/react.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{b as e,c as n,f as t,z as r}from"./chunk-
|
|
1
|
+
"use client";import{b as e,c as n,f as t,z as r}from"./chunk-K6ETEZER.js";import{b as o}from"./chunk-G2QGDYNV.js";import"./chunk-ILX63XAJ.js";import"./chunk-DH22G2S5.js";import"./chunk-RPY7OOOR.js";import"./chunk-53M6AOAX.js";import"./chunk-WGISPOJV.js";import"./chunk-PLSWBSSX.js";import{useEffect as s,useRef as c}from"react";function u(e){let n=c(null);s(()=>{if(n.current&&function(e,n){return[...new Set([...Object.keys(e),...Object.keys(n)])].every(t=>{if("shortcuts"===t||"features"===t||"frame"===t){let r=e[t]??{},o=n[t]??{};return Object.keys({...r,...o}).every(e=>Object.is(r[e],o[e]))}if("design"===t){let t=e.design,r=n.design;if(!t||!r)return t===r;let o=t.themes??[],s=r.themes??[];return t.tokens===r.tokens&&t.components===r.components&&o.length===s.length&&o.every((e,n)=>e===s[n])}if("onboarding"!==t)return Object.is(e[t],n[t]);let r=e.onboarding,o=n.onboarding;return r&&o?Object.keys({...r,...o}).every(e=>"sites"===e?r.sites?.length===o.sites?.length&&(r.sites??[]).every((e,n)=>e===o.sites?.[n]):Object.is(r[e],o[e])):r===o})}(n.current.config,e)||(n.current?.controller.destroy(),n.current=null,!1===e.enabled))return;let t={...e,...e.onboarding?{onboarding:{...e.onboarding,...e.onboarding.sites?{sites:[...e.onboarding.sites]}:{}}}:{}};n.current={config:t,controller:o(t)}}),s(()=>()=>{n.current?.controller.destroy(),n.current=null},[])}function i(t){let r=c(null),o=c(null);return o.current||(o.current=e=>{r.current=e}),s(()=>{if(!0===t.enabled&&r.current)return e(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component]),s(()=>{!0===t.enabled&&n(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component,t.props,t.onChange]),{ref:o.current,"data-komo-inspectable":t.component.id}}function l(e){s(()=>{if(!0!==e.enabled)return;let n=e.root??document.documentElement;return t(n,e.tokens)},[e.root,e.tokens,e.enabled])}export{r as cssVariableTokens,u as useKomo,l as useKomoDesignTokens,i as useKomoInspectable};
|