@designbasekorea/ui-wc 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE-WORLD-MAP.md +10 -0
  3. package/README.md +83 -0
  4. package/dist/esm/components/db-achievement-list.d.ts +2 -0
  5. package/dist/esm/components/db-achievement-list.js +1 -1
  6. package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
  7. package/dist/esm/components/db-activity-heatmap.js +1 -1
  8. package/dist/esm/components/db-ad-banner.d.ts +2 -0
  9. package/dist/esm/components/db-ad-banner.js +1 -1
  10. package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
  11. package/dist/esm/components/db-ai-chat-list.js +1 -1
  12. package/dist/esm/components/db-ai-chat.d.ts +2 -0
  13. package/dist/esm/components/db-ai-chat.js +1 -1
  14. package/dist/esm/components/db-ai-file-tree.js +1 -1
  15. package/dist/esm/components/db-alert.d.ts +1 -0
  16. package/dist/esm/components/db-alert.js +1 -1
  17. package/dist/esm/components/db-audio-player.d.ts +2 -0
  18. package/dist/esm/components/db-audio-player.js +1 -1
  19. package/dist/esm/components/db-avatar.d.ts +1 -0
  20. package/dist/esm/components/db-avatar.js +1 -1
  21. package/dist/esm/components/db-banner.d.ts +2 -0
  22. package/dist/esm/components/db-banner.js +1 -1
  23. package/dist/esm/components/db-button.d.ts +7 -1
  24. package/dist/esm/components/db-button.js +1 -1
  25. package/dist/esm/components/db-calendar.d.ts +5 -0
  26. package/dist/esm/components/db-calendar.js +1 -1
  27. package/dist/esm/components/db-card.d.ts +1 -0
  28. package/dist/esm/components/db-card.js +1 -1
  29. package/dist/esm/components/db-chat-composer.d.ts +3 -0
  30. package/dist/esm/components/db-chat-composer.js +1 -1
  31. package/dist/esm/components/db-chat-message.d.ts +2 -0
  32. package/dist/esm/components/db-chat-message.js +1 -1
  33. package/dist/esm/components/db-chat-room.d.ts +1 -0
  34. package/dist/esm/components/db-chat-room.js +1 -1
  35. package/dist/esm/components/db-chat-typing.d.ts +2 -0
  36. package/dist/esm/components/db-chat-typing.js +1 -1
  37. package/dist/esm/components/db-chat-widget.d.ts +9 -0
  38. package/dist/esm/components/db-chat-widget.js +1 -1
  39. package/dist/esm/components/db-chip.d.ts +2 -0
  40. package/dist/esm/components/db-chip.js +1 -1
  41. package/dist/esm/components/db-code-block.d.ts +1 -0
  42. package/dist/esm/components/db-code-block.js +1 -1
  43. package/dist/esm/components/db-color-picker.d.ts +4 -0
  44. package/dist/esm/components/db-color-picker.js +1 -1
  45. package/dist/esm/components/db-color-swatch.d.ts +3 -0
  46. package/dist/esm/components/db-color-swatch.js +1 -1
  47. package/dist/esm/components/db-cookie-banner.d.ts +3 -0
  48. package/dist/esm/components/db-cookie-banner.js +1 -1
  49. package/dist/esm/components/db-countdown.d.ts +2 -1
  50. package/dist/esm/components/db-countdown.js +1 -1
  51. package/dist/esm/components/db-date-picker.d.ts +3 -0
  52. package/dist/esm/components/db-date-picker.js +1 -1
  53. package/dist/esm/components/db-dropdown.d.ts +1 -0
  54. package/dist/esm/components/db-dropdown.js +1 -1
  55. package/dist/esm/components/db-dropzone.d.ts +2 -0
  56. package/dist/esm/components/db-dropzone.js +1 -1
  57. package/dist/esm/components/db-email-verify.d.ts +1 -0
  58. package/dist/esm/components/db-email-verify.js +1 -1
  59. package/dist/esm/components/db-file-uploader.d.ts +2 -0
  60. package/dist/esm/components/db-file-uploader.js +1 -1
  61. package/dist/esm/components/db-form.d.ts +2 -0
  62. package/dist/esm/components/db-form.js +1 -1
  63. package/dist/esm/components/db-gantt.d.ts +2 -0
  64. package/dist/esm/components/db-gantt.js +1 -1
  65. package/dist/esm/components/db-image-list.d.ts +3 -0
  66. package/dist/esm/components/db-image-list.js +1 -1
  67. package/dist/esm/components/db-image.d.ts +1 -0
  68. package/dist/esm/components/db-image.js +1 -1
  69. package/dist/esm/components/db-input-group.d.ts +30 -0
  70. package/dist/esm/components/db-input-group.js +1 -0
  71. package/dist/esm/components/db-input.d.ts +1 -0
  72. package/dist/esm/components/db-input.js +1 -1
  73. package/dist/esm/components/db-kanban.d.ts +3 -0
  74. package/dist/esm/components/db-kanban.js +1 -1
  75. package/dist/esm/components/db-lightbox.d.ts +2 -0
  76. package/dist/esm/components/db-lightbox.js +1 -1
  77. package/dist/esm/components/db-list.d.ts +2 -0
  78. package/dist/esm/components/db-list.js +1 -1
  79. package/dist/esm/components/db-markdown-editor.d.ts +2 -0
  80. package/dist/esm/components/db-markdown-editor.js +1 -1
  81. package/dist/esm/components/db-menu-item.js +1 -1
  82. package/dist/esm/components/db-navbar.d.ts +3 -0
  83. package/dist/esm/components/db-navbar.js +1 -1
  84. package/dist/esm/components/db-node.d.ts +1 -0
  85. package/dist/esm/components/db-node.js +1 -1
  86. package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
  87. package/dist/esm/components/db-onboarding-modal.js +1 -1
  88. package/dist/esm/components/db-otp-input.d.ts +4 -1
  89. package/dist/esm/components/db-otp-input.js +1 -1
  90. package/dist/esm/components/db-page-header.js +1 -1
  91. package/dist/esm/components/db-popover.d.ts +1 -0
  92. package/dist/esm/components/db-popover.js +1 -1
  93. package/dist/esm/components/db-progress-step.d.ts +2 -0
  94. package/dist/esm/components/db-progress-step.js +1 -1
  95. package/dist/esm/components/db-range-slider.d.ts +1 -0
  96. package/dist/esm/components/db-range-slider.js +1 -1
  97. package/dist/esm/components/db-rating.d.ts +1 -0
  98. package/dist/esm/components/db-rating.js +1 -1
  99. package/dist/esm/components/db-search-bar.d.ts +2 -0
  100. package/dist/esm/components/db-search-bar.js +1 -1
  101. package/dist/esm/components/db-section-logo-cloud.js +1 -1
  102. package/dist/esm/components/db-selection-bar.d.ts +42 -0
  103. package/dist/esm/components/db-selection-bar.js +1 -0
  104. package/dist/esm/components/db-share.d.ts +5 -0
  105. package/dist/esm/components/db-share.js +1 -1
  106. package/dist/esm/components/db-sidebar.d.ts +3 -0
  107. package/dist/esm/components/db-sidebar.js +1 -1
  108. package/dist/esm/components/db-signature.d.ts +2 -0
  109. package/dist/esm/components/db-signature.js +1 -1
  110. package/dist/esm/components/db-spinner.d.ts +2 -0
  111. package/dist/esm/components/db-spinner.js +1 -1
  112. package/dist/esm/components/db-stepper.d.ts +2 -0
  113. package/dist/esm/components/db-stepper.js +1 -1
  114. package/dist/esm/components/db-table.d.ts +2 -0
  115. package/dist/esm/components/db-table.js +1 -1
  116. package/dist/esm/components/db-tabs.d.ts +1 -0
  117. package/dist/esm/components/db-tabs.js +1 -1
  118. package/dist/esm/components/db-ticket.js +1 -1
  119. package/dist/esm/components/db-time-picker.d.ts +2 -0
  120. package/dist/esm/components/db-time-picker.js +1 -1
  121. package/dist/esm/components/db-timeline.d.ts +4 -0
  122. package/dist/esm/components/db-timeline.js +1 -1
  123. package/dist/esm/components/db-toast.d.ts +2 -0
  124. package/dist/esm/components/db-toast.js +1 -1
  125. package/dist/esm/components/db-tool-layout.d.ts +92 -0
  126. package/dist/esm/components/db-tool-layout.js +1 -0
  127. package/dist/esm/components/db-tool-panel.d.ts +50 -0
  128. package/dist/esm/components/db-tool-panel.js +1 -0
  129. package/dist/esm/components/db-top-banner.d.ts +2 -0
  130. package/dist/esm/components/db-top-banner.js +1 -1
  131. package/dist/esm/components/db-video-player.d.ts +3 -0
  132. package/dist/esm/components/db-video-player.js +1 -1
  133. package/dist/esm/components/db-world-map.d.ts +60 -0
  134. package/dist/esm/components/db-world-map.js +1 -0
  135. package/dist/esm/components/db-youtube-player.d.ts +2 -0
  136. package/dist/esm/components/db-youtube-player.js +1 -1
  137. package/dist/esm/components/db-zoom-control.d.ts +52 -0
  138. package/dist/esm/components/db-zoom-control.js +1 -0
  139. package/dist/esm/components/input-validation.js +1 -1
  140. package/dist/esm/components/paper-card.d.ts +2 -0
  141. package/dist/esm/components/paper-card.js +1 -1
  142. package/dist/esm/core/i18n-copy.js +1 -1
  143. package/dist/esm/core/i18n-en.js +1 -1
  144. package/dist/esm/core/i18n.d.ts +34 -1
  145. package/dist/esm/core/i18n.js +1 -1
  146. package/dist/esm/helpers/world-countries.js +1 -0
  147. package/dist/esm/helpers/world-land.js +1 -0
  148. package/dist/esm/index.d.ts +7 -1
  149. package/dist/esm/index.js +1 -1
  150. package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
  151. package/dist/index.cjs +1 -1
  152. package/dist/index.css +1 -1
  153. package/dist/index.d.ts +484 -6
  154. package/dist/index.esm.js +1 -1
  155. package/dist/react/index.cjs +1 -1
  156. package/dist/react/index.d.ts +871 -71
  157. package/dist/react/index.esm.js +1 -1
  158. package/package.json +4 -3
@@ -1 +1 @@
1
- import{TextFieldState as t,TEXT_FIELD_ATTRIBUTES as e,upgradeTextProperties as s,textFieldDescription as i}from"../core/text-field-state.js";import{t as n,dbText as a}from"../core/i18n.js";import{getDbComponentIconSize as r,createDbIcon as d}from"./db-icons.js";import{getPasswordValidation as u}from"./input-validation.js";import{attachNumberScrub as l,readNumericAttribute as o}from"./number-scrub.js";import{dbUid as h}from"../core/uid.js";import{coerceToContract as c}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{INPUT_TYPES as b,INPUT_SIZES as p}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const g=new Set(["arrow-bar-left","arrow-bar-right","caret-down-filled","chevron-down","chevron-left","chevron-right","circle-checked","close","error-filled","edit","hide","info-filled","lock","mail","mobile","plus","search","share-alt","show","sparkle","trash","user","warning-filled"]);class DbInput extends HTMLElement{constructor(){super(...arguments),this.shapeKey="",this.formState=new t(this,()=>{this.touched=!1,this.updateDynamicUI()}),this.passwordVisible=!1,this.isFocused=!1,this.touched=!1,this.isScrubbing=!1,this.handleInput=t=>{t.stopPropagation();const e=t.target;this.updateDynamicUI(),this.dispatchEvent(new InputEvent("input",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:e.value,nativeEvent:t},bubbles:!0,composed:!0}))},this.handleChange=t=>{t.stopPropagation();const e=t.target;this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.value,nativeEvent:t},bubbles:!0,composed:!0}))},this.handleFocus=t=>{this.isFocused=!0,this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-focus",{detail:{nativeEvent:t},bubbles:!0,composed:!0}))},this.handleBlur=t=>{this.isFocused=!1,this.touched=!0,this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-blur",{detail:{nativeEvent:t},bubbles:!0,composed:!0}))},this.handlePasswordToggle=()=>{this.passwordVisible=!this.passwordVisible,this.render()},this.handleSearchClear=()=>{this.input&&(this.input.value="",this.setAttribute("value",""),this.input.focus(),this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:"",nativeEvent:null},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0})))}}static get observedAttributes(){return["type","label","placeholder","value","default-value","size","disabled","readonly","required","error","error-message","helper-text","full-width","name","start-icon","end-icon","validate","validation-visibility","validate-on-blur","password-min-length","scrubbable","scrub-step","scrub-sensitivity","min","max","step",...e]}get value(){return this.input?.value??this.getAttribute("value")??""}set value(t){this.setAttribute("value",t),this.input&&(this.input.value=t),this.updateDynamicUI()}get defaultValue(){return this.formState.defaultValue}set defaultValue(t){this.setAttribute("default-value",t)}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",t)}get type(){return c(this.getAttribute("type"),b,"text")}set type(t){this.setAttribute("type",t)}get size(){return c(this.getAttribute("size"),p,"m")}set size(t){this.setAttribute("size",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t)}connectedCallback(){s(this,["value","defaultValue","name","required","type","size","disabled","readOnly"]),this.render()}disconnectedCallback(){this.formState.disconnect(),this.detachScrub?.(),this.detachScrub=void 0}attributeChangedCallback(t){if("value"!==t||!this.isScrubbing){if("value"===t&&this.input){const t=this.getAttribute("value")??"";return this.input.value!==t&&(this.input.value=t),this.formState.syncValue(this.input),void this.updateDynamicUI()}this.isConnected&&this.render()}}focus(t){this.input?.focus(t)}get passwordMinLength(){return Number(this.getAttribute("password-min-length")||8)}get validationVisibility(){return this.getAttribute("validation-visibility")||"focus"}get validateOnBlur(){return!this.hasAttribute("validate-on-blur")||"false"!==this.getAttribute("validate-on-blur")}get isValidationEnabled(){return this.hasAttribute("validate")}getIconSize(){return r(this.size)}resolveIconName(t){const e=this.getAttribute(t);if(e&&g.has(e))return e}resolveStartIcon(){const t=this.resolveIconName("start-icon");return t||("search"===this.type?"search":void 0)}getCurrentValue(){return this.input?.value??this.getAttribute("value")??this.getAttribute("default-value")??""}buildStructure(t){const make=(t,e)=>{const s=document.createElement(t);return s.className=e,s},e=[];if(t.label){const s=document.createElement("label");s.className="designbase-wc-input__label",s.htmlFor=t.fieldId,e.push(s)}const s=make("span","designbase-wc-input__wrapper");if(t.startIcon){const t=make("span","designbase-wc-input__start-icon");t.setAttribute("aria-hidden","true"),s.append(t)}const i=document.createElement("input");if(i.className="designbase-wc-input__field",i.id=t.fieldId,s.append(i),t.isPassword){const t=document.createElement("button");t.type="button",t.className="designbase-wc-input__password-toggle",s.append(t)}if(t.isSearch){const t=document.createElement("button");t.type="button",t.className="designbase-wc-input__clear-button",t.hidden=!0,s.append(t)}if(t.endIcon&&!t.isPassword&&!t.isSearch){const t=make("span","designbase-wc-input__end-icon");t.setAttribute("aria-hidden","true"),s.append(t)}if(e.push(s),this.isValidationEnabled&&t.isPassword){const s=make("div","designbase-wc-input__validation-slot");s.id=t.validationId,e.push(s)}const n=make("p","designbase-wc-input__helper-text");n.id=t.helperId;const a=make("p","designbase-wc-input__error-message");a.id=t.errorId,e.push(n,a),this.replaceChildren(...e)}render(){const t=this.getCurrentValue(),e=b.includes(this.type)?this.type:"text",s="search"===e,i="password"===e,a=i&&this.passwordVisible||s?"text":e,r=this.getAttribute("label")||"",d=this.getAttribute("helper-text")||"",u=this.getAttribute("error-message")||"",c=this.hasAttribute("error"),g=this.resolveStartIcon(),w=this.resolveIconName("end-icon");this.classList.add("designbase-wc-input"),p.forEach(t=>this.classList.remove(`designbase-wc-input--${t}`)),this.classList.add(`designbase-wc-input--${p.includes(this.size)?this.size:"m"}`),this.classList.toggle("designbase-wc-input--error",c),this.classList.toggle("designbase-wc-input--disabled",this.disabled),this.classList.toggle("designbase-wc-input--readonly",this.readOnly),this.classList.toggle("designbase-wc-input--full-width",this.hasAttribute("full-width")),this.classList.toggle("designbase-wc-input--with-start-icon",Boolean(g));const m=s&&t.length>0&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--with-end-icon",Boolean(w&&!i&&!s)||i||m),this.classList.toggle("designbase-wc-input--with-password-toggle",i),this.classList.toggle("designbase-wc-input--with-search-clear",m);const v=this.hasAttribute("scrubbable")&&"number"===e&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--scrubbable",v),this.classList.toggle("designbase-wc-input--scrubbing",this.isScrubbing);const _=this.getAttribute("id")||h("db-input");this.hasAttribute("id")||this.setAttribute("id",_);const y=`${_}-field`,f=`${_}-helper`,A=`${_}-error`,S=`${_}-validation`,E=this.getAttribute("min"),I=this.getAttribute("max"),q=this.getAttribute("step"),C=[r?"L":"",g?"S":"",!w||i||s?"":"E",i?"P":"",s?"C":"",this.isValidationEnabled&&i?"V":""].join("");this.shapeKey===C&&this.input?.isConnected||(this.buildStructure({label:r,fieldId:y,helperId:f,errorId:A,validationId:S,startIcon:g,endIcon:w,isPassword:i,isSearch:s}),this.shapeKey=C);const V=this.querySelector(".designbase-wc-input__label");if(V&&(V.htmlFor=y,V.textContent=r,this.hasAttribute("required"))){const t=document.createElement("span");t.setAttribute("aria-hidden","true"),t.textContent=" *",V.append(t)}const L=this.querySelector("input.designbase-wc-input__field");if(L){L.id=y,L.type!==a&&(L.type=a),L.placeholder=this.getAttribute("placeholder")||"",L.disabled=this.disabled,L.readOnly=this.readOnly,L.required=this.hasAttribute("required"),L.name=this.getAttribute("name")||"",L.setAttribute("aria-invalid",String(c)),s?L.setAttribute("role","searchbox"):L.removeAttribute("role");for(const[t,e]of[["min",E],["max",I],["step",q]])null!==e?L.setAttribute(t,e):L.removeAttribute(t)}const x=this.querySelector(".designbase-wc-input__password-toggle");x&&(x.disabled=this.disabled,x.setAttribute("aria-label",n(this.passwordVisible?"input.hidePassword":"input.showPassword"))),this.querySelector(".designbase-wc-input__clear-button")?.setAttribute("aria-label",n("input.clearSearch"));const $=this.querySelector(".designbase-wc-input__helper-text");$&&($.id=f,$.textContent=d,$.hidden=!d||c);const P=this.querySelector(".designbase-wc-input__error-message");P&&(P.id=A,P.textContent=u,P.hidden=!c||!u),this.querySelector(".designbase-wc-input__validation-slot")?.setAttribute("id",S),this.mountIcons(g,!w||i||s?void 0:w,i);const k=this.querySelector("input.designbase-wc-input__field")||void 0;k&&(k.value!==t&&(k.value=t),k!==this.input&&(k.addEventListener("input",this.handleInput),k.addEventListener("change",this.handleChange),k.addEventListener("focus",this.handleFocus),k.addEventListener("blur",this.handleBlur))),this.input=k,k&&this.formState.sync(k);const D=this.querySelector(".designbase-wc-input__password-toggle");D&&!D.dataset.wcBound&&(D.dataset.wcBound="true",D.addEventListener("click",this.handlePasswordToggle));const z=this.querySelector(".designbase-wc-input__clear-button");z&&!z.dataset.wcBound&&(z.dataset.wcBound="true",z.addEventListener("click",this.handleSearchClear)),this.detachScrub?.(),this.detachScrub=void 0,v&&this.input&&(this.detachScrub=l(this.input,{isEnabled:()=>this.hasAttribute("scrubbable")&&"number"===this.type,isInteractive:()=>!this.disabled&&!this.readOnly,getValue:()=>this.getCurrentValue(),getStep:()=>o(this,"scrub-step")??o(this,"step")??1,getMin:()=>o(this,"min"),getMax:()=>o(this,"max"),getSensitivity:()=>o(this,"scrub-sensitivity")??4,onValueChange:t=>this.applyScrubValue(t),onScrubStateChange:t=>{this.isScrubbing=t,this.classList.toggle("designbase-wc-input--scrubbing",t),!t&&this.input&&this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.input.value,nativeEvent:null},bubbles:!0,composed:!0}))}})),this.updateDynamicUI()}mountIcons(t,e,s=!1){const i=this.getIconSize();if(t){const e=this.querySelector(".designbase-wc-input__start-icon");e?.replaceChildren(d(t,i))}if(e){const t=this.querySelector(".designbase-wc-input__end-icon");t?.replaceChildren(d(e,i))}if(s){const t=this.querySelector(".designbase-wc-input__password-toggle");t?.replaceChildren(d(this.passwordVisible?"hide":"show",i))}const n=this.querySelector(".designbase-wc-input__clear-button");n?.replaceChildren(d("close",i))}shouldShowPasswordValidation(t){return!(!this.isValidationEnabled||"password"!==this.type)&&("never"!==this.validationVisibility&&("always"===this.validationVisibility||(this.isFocused||t.length>0)))}renderValidationMarkup(t){const e=u(t,this.passwordMinLength),s=Array.from({length:4},(t,s)=>`<span class="designbase-wc-input__password-strength-segment${s<e.score?` designbase-wc-input__password-strength-segment--${e.level}`:""}"></span>`).join(""),i=e.requirements.map(t=>`<li class="designbase-wc-input__password-requirement${t.met?" designbase-wc-input__password-requirement--met":""}">${t.met?'<span class="designbase-wc-input__password-requirement-icon" aria-hidden="true"></span>':'<span class="designbase-wc-input__password-requirement-icon" aria-hidden="true"><span class="designbase-wc-input__password-requirement-dot"></span></span>'}<span class="designbase-wc-input__password-requirement-label">${this.escape(t.label)}</span></li>`).join("");return`\n <div class="designbase-wc-input__validation" aria-live="polite">\n <div class="designbase-wc-input__password-strength">\n <div class="designbase-wc-input__password-strength-bar" role="progressbar" aria-valuemin="0" aria-valuemax="4" aria-valuenow="${e.score}" aria-label="${a("비밀번호 강도")}">${s}</div>\n <span class="designbase-wc-input__password-strength-label designbase-wc-input__password-strength-label--${e.level}">${e.levelLabel}</span>\n </div>\n <ul class="designbase-wc-input__password-requirements">${i}</ul>\n </div>\n `}updateDynamicUI(){const t=this.getCurrentValue(),e="search"===this.type&&t.length>0&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--with-search-clear",e);const s=this.querySelector(".designbase-wc-input__clear-button");s&&(s.hidden=!e,s.replaceChildren(d("close",this.getIconSize())));const n=this.querySelector(".designbase-wc-input__validation-slot");if(n&&(this.shouldShowPasswordValidation(t)?(n.innerHTML=this.renderValidationMarkup(t),n.querySelectorAll(".designbase-wc-input__password-requirement--met .designbase-wc-input__password-requirement-icon").forEach(t=>{t.replaceChildren(d("circle-checked",12))})):n.innerHTML=""),this.input){const e=`${this.getAttribute("id")}-helper`,s=`${this.getAttribute("id")}-error`,n=`${this.getAttribute("id")}-validation`,a=this.getAttribute("helper-text")||"",r=this.getAttribute("error-message")||"",d=this.hasAttribute("error"),u=i(this,a&&!d?e:"",this.shouldShowPasswordValidation(t)?n:"",d&&r?s:"")||void 0;u?this.input.setAttribute("aria-describedby",u):this.input.removeAttribute("aria-describedby")}}applyScrubValue(t){this.input&&(this.input.value=t,this.setAttribute("value",t),this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:t,nativeEvent:null},bubbles:!0,composed:!0})))}escape(t){return t.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[t]||t))}}customElements.get("db-input")||customElements.define("db-input",DbInput);export{DbInput};
1
+ import{TextFieldState as t,TEXT_FIELD_ATTRIBUTES as e,upgradeTextProperties as s,textFieldDescription as i}from"../core/text-field-state.js";import{subscribeDbLocale as n,t as a,dbText as r}from"../core/i18n.js";import{getDbComponentIconSize as d,createDbIcon as u}from"./db-icons.js";import{getPasswordValidation as l}from"./input-validation.js";import{attachNumberScrub as o,readNumericAttribute as h}from"./number-scrub.js";import{dbUid as c}from"../core/uid.js";import{coerceToContract as b}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{INPUT_TYPES as p,INPUT_SIZES as g}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const w=new Set(["arrow-bar-left","arrow-bar-right","caret-down-filled","chevron-down","chevron-left","chevron-right","circle-checked","close","error-filled","edit","hide","info-filled","lock","mail","mobile","plus","search","share-alt","show","sparkle","trash","user","warning-filled"]);class DbInput extends HTMLElement{constructor(){super(...arguments),this.shapeKey="",this.formState=new t(this,()=>{this.touched=!1,this.updateDynamicUI()}),this.passwordVisible=!1,this.isFocused=!1,this.touched=!1,this.isScrubbing=!1,this.handleInput=t=>{t.stopPropagation();const e=t.target;this.updateDynamicUI(),this.dispatchEvent(new InputEvent("input",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:e.value,nativeEvent:t},bubbles:!0,composed:!0}))},this.handleChange=t=>{t.stopPropagation();const e=t.target;this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.value,nativeEvent:t},bubbles:!0,composed:!0}))},this.handleFocus=t=>{this.isFocused=!0,this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-focus",{detail:{nativeEvent:t},bubbles:!0,composed:!0}))},this.handleBlur=t=>{this.isFocused=!1,this.touched=!0,this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-blur",{detail:{nativeEvent:t},bubbles:!0,composed:!0}))},this.handlePasswordToggle=()=>{this.passwordVisible=!this.passwordVisible,this.render()},this.handleSearchClear=()=>{this.input&&(this.input.value="",this.setAttribute("value",""),this.input.focus(),this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:"",nativeEvent:null},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0})))}}static get observedAttributes(){return["type","label","placeholder","value","default-value","size","disabled","readonly","required","error","error-message","helper-text","full-width","name","start-icon","end-icon","validate","validation-visibility","validate-on-blur","password-min-length","scrubbable","scrub-step","scrub-sensitivity","min","max","step",...e]}get value(){return this.input?.value??this.getAttribute("value")??""}set value(t){this.setAttribute("value",t),this.input&&(this.input.value=t),this.updateDynamicUI()}get defaultValue(){return this.formState.defaultValue}set defaultValue(t){this.setAttribute("default-value",t)}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",t)}get type(){return b(this.getAttribute("type"),p,"text")}set type(t){this.setAttribute("type",t)}get size(){return b(this.getAttribute("size"),g,"m")}set size(t){this.setAttribute("size",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t)}connectedCallback(){s(this,["value","defaultValue","name","required","type","size","disabled","readOnly"]),this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=n(()=>this.render())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.formState.disconnect(),this.detachScrub?.(),this.detachScrub=void 0}attributeChangedCallback(t){if("value"!==t||!this.isScrubbing){if("value"===t&&this.input){const t=this.getAttribute("value")??"";return this.input.value!==t&&(this.input.value=t),this.formState.syncValue(this.input),void this.updateDynamicUI()}this.isConnected&&this.render()}}focus(t){this.input?.focus(t)}get passwordMinLength(){return Number(this.getAttribute("password-min-length")||8)}get validationVisibility(){return this.getAttribute("validation-visibility")||"focus"}get validateOnBlur(){return!this.hasAttribute("validate-on-blur")||"false"!==this.getAttribute("validate-on-blur")}get isValidationEnabled(){return this.hasAttribute("validate")}getIconSize(){return d(this.size)}resolveIconName(t){const e=this.getAttribute(t);if(e&&w.has(e))return e}resolveStartIcon(){const t=this.resolveIconName("start-icon");return t||("search"===this.type?"search":void 0)}getCurrentValue(){return this.input?.value??this.getAttribute("value")??this.getAttribute("default-value")??""}buildStructure(t){const make=(t,e)=>{const s=document.createElement(t);return s.className=e,s},e=[];if(t.label){const s=document.createElement("label");s.className="designbase-wc-input__label",s.htmlFor=t.fieldId,e.push(s)}const s=make("span","designbase-wc-input__wrapper");if(t.startIcon){const t=make("span","designbase-wc-input__start-icon");t.setAttribute("aria-hidden","true"),s.append(t)}const i=document.createElement("input");if(i.className="designbase-wc-input__field",i.id=t.fieldId,s.append(i),t.isPassword){const t=document.createElement("button");t.type="button",t.className="designbase-wc-input__password-toggle",s.append(t)}if(t.isSearch){const t=document.createElement("button");t.type="button",t.className="designbase-wc-input__clear-button",t.hidden=!0,s.append(t)}if(t.endIcon&&!t.isPassword&&!t.isSearch){const t=make("span","designbase-wc-input__end-icon");t.setAttribute("aria-hidden","true"),s.append(t)}if(e.push(s),this.isValidationEnabled&&t.isPassword){const s=make("div","designbase-wc-input__validation-slot");s.id=t.validationId,e.push(s)}const n=make("p","designbase-wc-input__helper-text");n.id=t.helperId;const a=make("p","designbase-wc-input__error-message");a.id=t.errorId,e.push(n,a),this.replaceChildren(...e)}render(){const t=this.getCurrentValue(),e=p.includes(this.type)?this.type:"text",s="search"===e,i="password"===e,n=i&&this.passwordVisible||s?"text":e,r=this.getAttribute("label")||"",d=this.getAttribute("helper-text")||"",u=this.getAttribute("error-message")||"",l=this.hasAttribute("error"),b=this.resolveStartIcon(),w=this.resolveIconName("end-icon");this.classList.add("designbase-wc-input"),g.forEach(t=>this.classList.remove(`designbase-wc-input--${t}`)),this.classList.add(`designbase-wc-input--${g.includes(this.size)?this.size:"m"}`),this.classList.toggle("designbase-wc-input--error",l),this.classList.toggle("designbase-wc-input--disabled",this.disabled),this.classList.toggle("designbase-wc-input--readonly",this.readOnly),this.classList.toggle("designbase-wc-input--full-width",this.hasAttribute("full-width")),this.classList.toggle("designbase-wc-input--with-start-icon",Boolean(b));const m=s&&t.length>0&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--with-end-icon",Boolean(w&&!i&&!s)||i||m),this.classList.toggle("designbase-wc-input--with-password-toggle",i),this.classList.toggle("designbase-wc-input--with-search-clear",m);const v=this.hasAttribute("scrubbable")&&"number"===e&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--scrubbable",v),this.classList.toggle("designbase-wc-input--scrubbing",this.isScrubbing);const _=this.getAttribute("id")||c("db-input");this.hasAttribute("id")||this.setAttribute("id",_);const y=`${_}-field`,f=`${_}-helper`,A=`${_}-error`,S=`${_}-validation`,E=this.getAttribute("min"),I=this.getAttribute("max"),q=this.getAttribute("step"),C=[r?"L":"",b?"S":"",!w||i||s?"":"E",i?"P":"",s?"C":"",this.isValidationEnabled&&i?"V":""].join("");this.shapeKey===C&&this.input?.isConnected||(this.buildStructure({label:r,fieldId:y,helperId:f,errorId:A,validationId:S,startIcon:b,endIcon:w,isPassword:i,isSearch:s}),this.shapeKey=C);const L=this.querySelector(".designbase-wc-input__label");if(L&&(L.htmlFor=y,L.textContent=r,this.hasAttribute("required"))){const t=document.createElement("span");t.setAttribute("aria-hidden","true"),t.textContent=" *",L.append(t)}const V=this.querySelector("input.designbase-wc-input__field");if(V){V.id=y,V.type!==n&&(V.type=n),V.placeholder=this.getAttribute("placeholder")||"",V.disabled=this.disabled,V.readOnly=this.readOnly,V.required=this.hasAttribute("required"),V.name=this.getAttribute("name")||"",V.setAttribute("aria-invalid",String(l)),s?V.setAttribute("role","searchbox"):V.removeAttribute("role");for(const[t,e]of[["min",E],["max",I],["step",q]])null!==e?V.setAttribute(t,e):V.removeAttribute(t)}const x=this.querySelector(".designbase-wc-input__password-toggle");x&&(x.disabled=this.disabled,x.setAttribute("aria-label",a(this.passwordVisible?"input.hidePassword":"input.showPassword"))),this.querySelector(".designbase-wc-input__clear-button")?.setAttribute("aria-label",a("input.clearSearch"));const $=this.querySelector(".designbase-wc-input__helper-text");$&&($.id=f,$.textContent=d,$.hidden=!d||l);const P=this.querySelector(".designbase-wc-input__error-message");P&&(P.id=A,P.textContent=u,P.hidden=!l||!u),this.querySelector(".designbase-wc-input__validation-slot")?.setAttribute("id",S),this.mountIcons(b,!w||i||s?void 0:w,i);const k=this.querySelector("input.designbase-wc-input__field")||void 0;k&&(k.value!==t&&(k.value=t),k!==this.input&&(k.addEventListener("input",this.handleInput),k.addEventListener("change",this.handleChange),k.addEventListener("focus",this.handleFocus),k.addEventListener("blur",this.handleBlur))),this.input=k,k&&this.formState.sync(k);const D=this.querySelector(".designbase-wc-input__password-toggle");D&&!D.dataset.wcBound&&(D.dataset.wcBound="true",D.addEventListener("click",this.handlePasswordToggle));const z=this.querySelector(".designbase-wc-input__clear-button");z&&!z.dataset.wcBound&&(z.dataset.wcBound="true",z.addEventListener("click",this.handleSearchClear)),this.detachScrub?.(),this.detachScrub=void 0,v&&this.input&&(this.detachScrub=o(this.input,{isEnabled:()=>this.hasAttribute("scrubbable")&&"number"===this.type,isInteractive:()=>!this.disabled&&!this.readOnly,getValue:()=>this.getCurrentValue(),getStep:()=>h(this,"scrub-step")??h(this,"step")??1,getMin:()=>h(this,"min"),getMax:()=>h(this,"max"),getSensitivity:()=>h(this,"scrub-sensitivity")??4,onValueChange:t=>this.applyScrubValue(t),onScrubStateChange:t=>{this.isScrubbing=t,this.classList.toggle("designbase-wc-input--scrubbing",t),!t&&this.input&&this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.input.value,nativeEvent:null},bubbles:!0,composed:!0}))}})),this.updateDynamicUI()}mountIcons(t,e,s=!1){const i=this.getIconSize();if(t){const e=this.querySelector(".designbase-wc-input__start-icon");e?.replaceChildren(u(t,i))}if(e){const t=this.querySelector(".designbase-wc-input__end-icon");t?.replaceChildren(u(e,i))}if(s){const t=this.querySelector(".designbase-wc-input__password-toggle");t?.replaceChildren(u(this.passwordVisible?"hide":"show",i))}const n=this.querySelector(".designbase-wc-input__clear-button");n?.replaceChildren(u("close",i))}shouldShowPasswordValidation(t){return!(!this.isValidationEnabled||"password"!==this.type)&&("never"!==this.validationVisibility&&("always"===this.validationVisibility||(this.isFocused||t.length>0)))}renderValidationMarkup(t){const e=l(t,this.passwordMinLength),s=Array.from({length:4},(t,s)=>`<span class="designbase-wc-input__password-strength-segment${s<e.score?` designbase-wc-input__password-strength-segment--${e.level}`:""}"></span>`).join(""),i=e.requirements.map(t=>`<li class="designbase-wc-input__password-requirement${t.met?" designbase-wc-input__password-requirement--met":""}">${t.met?'<span class="designbase-wc-input__password-requirement-icon" aria-hidden="true"></span>':'<span class="designbase-wc-input__password-requirement-icon" aria-hidden="true"><span class="designbase-wc-input__password-requirement-dot"></span></span>'}<span class="designbase-wc-input__password-requirement-label">${this.escape(t.label)}</span></li>`).join("");return`\n <div class="designbase-wc-input__validation" aria-live="polite">\n <div class="designbase-wc-input__password-strength">\n <div class="designbase-wc-input__password-strength-bar" role="progressbar" aria-valuemin="0" aria-valuemax="4" aria-valuenow="${e.score}" aria-label="${r("비밀번호 강도")}">${s}</div>\n <span class="designbase-wc-input__password-strength-label designbase-wc-input__password-strength-label--${e.level}">${e.levelLabel}</span>\n </div>\n <ul class="designbase-wc-input__password-requirements">${i}</ul>\n </div>\n `}updateDynamicUI(){const t=this.getCurrentValue(),e="search"===this.type&&t.length>0&&!this.disabled&&!this.readOnly;this.classList.toggle("designbase-wc-input--with-search-clear",e);const s=this.querySelector(".designbase-wc-input__clear-button");s&&(s.hidden=!e,s.replaceChildren(u("close",this.getIconSize())));const n=this.querySelector(".designbase-wc-input__validation-slot");if(n&&(this.shouldShowPasswordValidation(t)?(n.innerHTML=this.renderValidationMarkup(t),n.querySelectorAll(".designbase-wc-input__password-requirement--met .designbase-wc-input__password-requirement-icon").forEach(t=>{t.replaceChildren(u("circle-checked",12))})):n.innerHTML=""),this.input){const e=`${this.getAttribute("id")}-helper`,s=`${this.getAttribute("id")}-error`,n=`${this.getAttribute("id")}-validation`,a=this.getAttribute("helper-text")||"",r=this.getAttribute("error-message")||"",d=this.hasAttribute("error"),u=i(this,a&&!d?e:"",this.shouldShowPasswordValidation(t)?n:"",d&&r?s:"")||void 0;u?this.input.setAttribute("aria-describedby",u):this.input.removeAttribute("aria-describedby")}}applyScrubValue(t){this.input&&(this.input.value=t,this.setAttribute("value",t),this.updateDynamicUI(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:t,nativeEvent:null},bubbles:!0,composed:!0})))}escape(t){return t.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[t]||t))}}customElements.get("db-input")||customElements.define("db-input",DbInput);export{DbInput};
@@ -27,6 +27,7 @@ type DbKanbanColumn = {
27
27
  };
28
28
  declare class DbKanban extends HTMLElement {
29
29
  private dragState;
30
+ private unsubscribeLocale?;
30
31
  private dropTarget;
31
32
  static get observedAttributes(): string[];
32
33
  get columns(): DbKanbanColumn[];
@@ -52,6 +53,8 @@ declare class DbKanban extends HTMLElement {
52
53
  private formatDueDate;
53
54
  private getInitials;
54
55
  private createTag;
56
+ private priorityLabel;
57
+ private refreshLocale;
55
58
  private createPriorityBadge;
56
59
  private createAssignee;
57
60
  private bindCardDrag;
@@ -1 +1 @@
1
- import{dbText as e,getDbLocale as t,dbFormat as a}from"../core/i18n.js";import{createDbIcon as n}from"./db-icons.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{KANBAN_SIZES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r=d,i=["low","medium","high","urgent"],o={low:"낮음",medium:"보통",high:"높음",urgent:"긴급"};class DbKanban extends HTMLElement{constructor(){super(...arguments),this.dragState=null,this.dropTarget=null,this.handleBoardDragOver=e=>{if(!this.dragState)return;const t=e.target;t instanceof Element&&(t.closest(".designbase-wc-kanban__card")||t.closest(".designbase-wc-kanban__column-body"))||(e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move"))},this.handleBoardDrop=e=>{if(!this.dragState)return;const t=e.target;t instanceof Element&&(t.closest(".designbase-wc-kanban__card")||t.closest(".designbase-wc-kanban__column-body"))||(e.preventDefault(),this.commitDrop())}}static get observedAttributes(){return["columns","size","disabled","draggable","show-column-count","show-add-card","allow-cross-column","full-width","empty-column-text"]}get columns(){try{const e=JSON.parse(this.getAttribute("columns")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label",e("칸반 보드")),this.addEventListener("dragover",this.handleBoardDragOver),this.addEventListener("drop",this.handleBoardDrop),this.render()}disconnectedCallback(){this.removeEventListener("dragover",this.handleBoardDragOver),this.removeEventListener("drop",this.handleBoardDrop)}attributeChangedCallback(){this.isConnected&&this.render()}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}emitChange(e){this.columns=e,this.dispatchEvent(new CustomEvent("db-change",{detail:{columns:e},bubbles:!0,composed:!0}))}emitCardMove(e,t){this.columns=e,this.dispatchEvent(new CustomEvent("db-card-move",{detail:{...t,columns:e},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{columns:e},bubbles:!0,composed:!0}))}findCardLocation(e){for(const t of this.columns){const a=t.cards.findIndex(t=>t.id===e);if(a>=0)return{columnId:t.id,index:a}}return null}getAdjustedDropIndex(e,t){if(!this.dragState)return-1;const{columnId:a,cardIndex:n}=this.dragState;return a===e&&t>n?t-1:t}isValidDropTarget(e=this.dropTarget){if(!this.dragState||!e)return!1;const t=this.getAdjustedDropIndex(e.columnId,e.index);return!(t<0)&&(this.dragState.columnId!==e.columnId||t!==this.dragState.cardIndex)}moveCard(e,t,a){const n=this.findCardLocation(e);if(!n)return;const s=this.columns.map(e=>({...e,cards:[...e.cards]})),d=s.find(e=>e.id===n.columnId),r=s.find(e=>e.id===t);if(!d||!r)return;const[i]=d.cards.splice(n.index,1);if(!i)return;const o=this.getAdjustedDropIndex(t,a);r.cards.splice(Math.max(0,o),0,i),this.emitCardMove(s,{cardId:e,fromColumnId:n.columnId,toColumnId:t,fromIndex:n.index,toIndex:Math.max(0,o)})}setDropTarget(e){const t=e&&this.isValidDropTarget(e)?e:null;(this.dropTarget?`${this.dropTarget.columnId}:${this.dropTarget.index}`:"")!==(t?`${t.columnId}:${t.index}`:"")&&(this.dropTarget=t,this.updateDragClasses())}resetDragState(){this.dragState=null,this.dropTarget=null,this.classList.remove("designbase-wc-kanban--dragging"),this.updateDragClasses()}updateDragClasses(){const e=!!this.dragState;this.classList.toggle("designbase-wc-kanban--dragging",e),this.querySelectorAll(".designbase-wc-kanban__card").forEach(t=>{const a=t.dataset.cardId||"",n=e&&this.dragState?.cardId===a;t.classList.toggle("designbase-wc-kanban__card--dragged",n)}),this.querySelectorAll(".designbase-wc-kanban__column-body").forEach(e=>{const t=e.dataset.columnId||"",a=!!this.dropTarget&&this.dropTarget.columnId===t;e.classList.toggle("designbase-wc-kanban__column-body--drag-over",a)}),this.querySelectorAll(".designbase-wc-kanban__card").forEach(e=>{const t=e.dataset.columnId||"",a=Number(e.dataset.cardIndex||-1),n=!!this.dropTarget&&this.dropTarget.columnId===t&&this.dropTarget.index===a,s=this.columns.find(e=>e.id===t),d=!!this.dropTarget&&this.dropTarget.columnId===t&&s&&this.dropTarget.index===s.cards.length&&a===s.cards.length-1;e.classList.toggle("designbase-wc-kanban__card--drop-before",n),e.classList.toggle("designbase-wc-kanban__card--drop-after",d)})}getDropIndexFromPointer(e,t,a){const n=t.getBoundingClientRect();return e.clientY-n.top<n.height/2?a:a+1}getDropIndexFromColumnPointer(e,t){const a=Array.from(this.querySelectorAll(`.designbase-wc-kanban__column-body[data-column-id="${t}"] > .designbase-wc-kanban__card`));if(0===a.length)return 0;for(let t=0;t<a.length;t+=1){const n=a[t].getBoundingClientRect();if(e.clientY<n.top+n.height/2)return t}return a.length}commitDrop(){if(!this.dragState||!this.dropTarget||!this.isValidDropTarget())return void this.resetDragState();const{cardId:e}=this.dragState,{columnId:t,index:a}=this.dropTarget;this.resetDragState(),this.moveCard(e,t,a),this.render()}formatDueDate(e){const a=new Date(e);return Number.isNaN(a.getTime())?e:a.toLocaleDateString("ko"===t()?"ko-KR":"en-US",{month:"short",day:"numeric"})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e.charAt(0)).join("").slice(0,2).toUpperCase()}createTag(e){const t=document.createElement("span");return t.className=["designbase-wc-kanban__tag",e.variant&&`designbase-wc-kanban__tag--${e.variant}`].filter(Boolean).join(" "),t.textContent=e.label,t}createPriorityBadge(e){const t=document.createElement("span");return t.className=`designbase-wc-kanban__priority designbase-wc-kanban__priority--${e}`,t.textContent=o[e],t.setAttribute("aria-label",a("우선순위 {0}",[o[e]])),t}createAssignee(e){const t=document.createElement("div");if(t.className="designbase-wc-kanban__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.className="designbase-wc-kanban__assignee-avatar",a.src=e.avatar,a.alt=e.name,t.append(a)}else{const a=document.createElement("span");a.className="designbase-wc-kanban__assignee-initials",a.textContent=this.getInitials(e),t.append(a)}const a=document.createElement("span");return a.className="designbase-wc-kanban__assignee-name",a.textContent=e.name,t.append(a),t}bindCardDrag(e,t,a,n,s,d){e.draggable=s&&!d&&!t.disabled,e.addEventListener("dragstart",e=>{!s||d||t.disabled||(this.dragState={cardId:t.id,columnId:a,cardIndex:n},this.dropTarget=null,e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",t.id)),this.classList.add("designbase-wc-kanban--dragging"),this.updateDragClasses())}),e.addEventListener("dragover",t=>{if(!this.dragState)return;t.preventDefault(),t.stopPropagation(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");if(!this.getBool("allow-cross-column",!0)&&this.dragState.columnId!==a)return;const s=this.getDropIndexFromPointer(t,e,n);this.setDropTarget({columnId:a,index:s})}),e.addEventListener("dragleave",t=>{const a=e.getBoundingClientRect(),n=t.clientX-a.left,s=t.clientY-a.top;(n<0||n>a.width||s<0||s>a.height)&&this.setDropTarget(null)}),e.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.commitDrop()}),e.addEventListener("dragend",()=>{this.resetDragState(),this.render()})}createCard(e,t,a,s){const d=document.createElement("article");d.className=["designbase-wc-kanban__card",e.disabled&&"designbase-wc-kanban__card--disabled",e.priority&&`designbase-wc-kanban__card--priority-${e.priority}`].filter(Boolean).join(" "),d.dataset.cardId=e.id,d.dataset.columnId=t,d.dataset.cardIndex=String(a),d.setAttribute("role","listitem"),d.tabIndex=e.disabled?-1:0;const r=document.createElement("div");r.className="designbase-wc-kanban__card-title-row";const o=document.createElement("h4");if(o.className="designbase-wc-kanban__card-title",o.textContent=e.title,r.append(o),e.priority&&i.includes(e.priority)&&r.append(this.createPriorityBadge(e.priority)),d.append(r),e.description){const t=document.createElement("p");t.className="designbase-wc-kanban__card-description",t.textContent=e.description,d.append(t)}if(e.tags?.length){const t=document.createElement("div");t.className="designbase-wc-kanban__card-tags",e.tags.forEach(e=>t.append(this.createTag(e))),d.append(t)}const c=document.createElement("div");if(c.className="designbase-wc-kanban__card-footer",e.assignee&&c.append(this.createAssignee(e.assignee)),e.dueDate){const t=document.createElement("span");t.className="designbase-wc-kanban__due-date",t.append(n("calendar","l"===s.size?12:"m"===s.size?11:10));const a=document.createElement("span");a.textContent=this.formatDueDate(e.dueDate),t.append(a),c.append(t)}return c.childNodes.length>0&&d.append(c),d.addEventListener("click",a=>{s.disabled||this.dispatchEvent(new CustomEvent("db-card-click",{detail:{card:e,columnId:t},bubbles:!0,composed:!0}))}),d.addEventListener("keydown",a=>{"Enter"!==a.key&&" "!==a.key||(a.preventDefault(),this.dispatchEvent(new CustomEvent("db-card-click",{detail:{card:e,columnId:t},bubbles:!0,composed:!0})))}),this.bindCardDrag(d,e,t,a,s.draggable,s.disabled),d}createColumn(t,a){const s=document.createElement("section"),d=void 0!==t.limit&&t.cards.length>t.limit;s.className=["designbase-wc-kanban__column",d&&"designbase-wc-kanban__column--over-limit"].filter(Boolean).join(" "),s.dataset.columnId=t.id,s.setAttribute("role","group"),s.setAttribute("aria-label",t.title);const r=document.createElement("header");r.className="designbase-wc-kanban__column-header";const i=document.createElement("div");if(i.className="designbase-wc-kanban__column-title-wrap",t.color){const e=document.createElement("span");e.className="designbase-wc-kanban__column-color",e.style.backgroundColor=t.color,e.setAttribute("aria-hidden","true"),i.append(e)}const o=document.createElement("h3");if(o.className="designbase-wc-kanban__column-title",o.textContent=t.title,i.append(o),r.append(i),a.showColumnCount){const e=document.createElement("span");e.className="designbase-wc-kanban__column-count",e.textContent=void 0!==t.limit?`${t.cards.length}/${t.limit}`:String(t.cards.length),r.append(e)}s.append(r);const c=document.createElement("div");if(c.className="designbase-wc-kanban__column-body",c.dataset.columnId=t.id,c.setAttribute("role","list"),c.addEventListener("dragover",e=>{if(!this.dragState)return;e.preventDefault(),e.stopPropagation(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");if(!this.getBool("allow-cross-column",!0)&&this.dragState.columnId!==t.id)return;const a=this.getDropIndexFromColumnPointer(e,t.id);this.setDropTarget({columnId:t.id,index:a})}),c.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.commitDrop()}),0===t.cards.length){const e=document.createElement("div");e.className="designbase-wc-kanban__column-empty",e.textContent=a.emptyColumnText,c.append(e)}else t.cards.forEach((e,n)=>{c.append(this.createCard(e,t.id,n,{size:a.size,draggable:a.draggable,disabled:a.disabled}))});if(s.append(c),a.showAddCard&&!a.disabled){const d=document.createElement("button");d.type="button",d.className="designbase-wc-kanban__add-card",d.append(n("plus","l"===a.size?14:"m"===a.size?12:10));const r=document.createElement("span");r.textContent=e("카드 추가"),d.append(r),d.disabled=this.getBool("disabled"),d.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-add-card",{detail:{columnId:t.id},bubbles:!0,composed:!0}))}),s.append(d)}return s}render(){const e=s(this.getAttribute("size"),r,"s"),t=this.getBool("disabled"),a=this.getBool("draggable",!0),n=this.getBool("show-column-count",!0),d=this.getBool("show-add-card"),i=this.getAttribute("empty-column-text")||"카드가 없습니다";this.className=["designbase-wc-kanban",`designbase-wc-kanban--${e}`,this.getBool("full-width")&&"designbase-wc-kanban--full-width",t&&"designbase-wc-kanban--disabled",this.classList.contains("designbase-wc-kanban--dragging")&&"designbase-wc-kanban--dragging"].filter(Boolean).join(" ");const o=document.createElement("div");o.className="designbase-wc-kanban__board";const c=document.createDocumentFragment();this.columns.forEach(s=>{c.append(this.createColumn(s,{size:e,draggable:a,showColumnCount:n,showAddCard:d,emptyColumnText:i,disabled:t}))}),o.append(c),this.replaceChildren(o),this.updateDragClasses()}}customElements.get("db-kanban")||customElements.define("db-kanban",DbKanban);export{DbKanban};
1
+ import{dbText as e,subscribeDbLocale as t,getDbLocale as a,dbFormat as n}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{coerceToContract as r}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{KANBAN_SIZES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const i=d,o=["low","medium","high","urgent"],c={low:"낮음",medium:"보통",high:"높음",urgent:"긴급"};class DbKanban extends HTMLElement{constructor(){super(...arguments),this.dragState=null,this.dropTarget=null,this.handleBoardDragOver=e=>{if(!this.dragState)return;const t=e.target;t instanceof Element&&(t.closest(".designbase-wc-kanban__card")||t.closest(".designbase-wc-kanban__column-body"))||(e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move"))},this.handleBoardDrop=e=>{if(!this.dragState)return;const t=e.target;t instanceof Element&&(t.closest(".designbase-wc-kanban__card")||t.closest(".designbase-wc-kanban__column-body"))||(e.preventDefault(),this.commitDrop())}}static get observedAttributes(){return["columns","size","disabled","draggable","show-column-count","show-add-card","allow-cross-column","full-width","empty-column-text"]}get columns(){try{const e=JSON.parse(this.getAttribute("columns")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label",e("칸반 보드")),this.addEventListener("dragover",this.handleBoardDragOver),this.addEventListener("drop",this.handleBoardDrop),this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.refreshLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("dragover",this.handleBoardDragOver),this.removeEventListener("drop",this.handleBoardDrop)}attributeChangedCallback(){this.isConnected&&this.render()}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}emitChange(e){this.columns=e,this.dispatchEvent(new CustomEvent("db-change",{detail:{columns:e},bubbles:!0,composed:!0}))}emitCardMove(e,t){this.columns=e,this.dispatchEvent(new CustomEvent("db-card-move",{detail:{...t,columns:e},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{columns:e},bubbles:!0,composed:!0}))}findCardLocation(e){for(const t of this.columns){const a=t.cards.findIndex(t=>t.id===e);if(a>=0)return{columnId:t.id,index:a}}return null}getAdjustedDropIndex(e,t){if(!this.dragState)return-1;const{columnId:a,cardIndex:n}=this.dragState;return a===e&&t>n?t-1:t}isValidDropTarget(e=this.dropTarget){if(!this.dragState||!e)return!1;const t=this.getAdjustedDropIndex(e.columnId,e.index);return!(t<0)&&(this.dragState.columnId!==e.columnId||t!==this.dragState.cardIndex)}moveCard(e,t,a){const n=this.findCardLocation(e);if(!n)return;const s=this.columns.map(e=>({...e,cards:[...e.cards]})),r=s.find(e=>e.id===n.columnId),d=s.find(e=>e.id===t);if(!r||!d)return;const[i]=r.cards.splice(n.index,1);if(!i)return;const o=this.getAdjustedDropIndex(t,a);d.cards.splice(Math.max(0,o),0,i),this.emitCardMove(s,{cardId:e,fromColumnId:n.columnId,toColumnId:t,fromIndex:n.index,toIndex:Math.max(0,o)})}setDropTarget(e){const t=e&&this.isValidDropTarget(e)?e:null;(this.dropTarget?`${this.dropTarget.columnId}:${this.dropTarget.index}`:"")!==(t?`${t.columnId}:${t.index}`:"")&&(this.dropTarget=t,this.updateDragClasses())}resetDragState(){this.dragState=null,this.dropTarget=null,this.classList.remove("designbase-wc-kanban--dragging"),this.updateDragClasses()}updateDragClasses(){const e=!!this.dragState;this.classList.toggle("designbase-wc-kanban--dragging",e),this.querySelectorAll(".designbase-wc-kanban__card").forEach(t=>{const a=t.dataset.cardId||"",n=e&&this.dragState?.cardId===a;t.classList.toggle("designbase-wc-kanban__card--dragged",n)}),this.querySelectorAll(".designbase-wc-kanban__column-body").forEach(e=>{const t=e.dataset.columnId||"",a=!!this.dropTarget&&this.dropTarget.columnId===t;e.classList.toggle("designbase-wc-kanban__column-body--drag-over",a)}),this.querySelectorAll(".designbase-wc-kanban__card").forEach(e=>{const t=e.dataset.columnId||"",a=Number(e.dataset.cardIndex||-1),n=!!this.dropTarget&&this.dropTarget.columnId===t&&this.dropTarget.index===a,s=this.columns.find(e=>e.id===t),r=!!this.dropTarget&&this.dropTarget.columnId===t&&s&&this.dropTarget.index===s.cards.length&&a===s.cards.length-1;e.classList.toggle("designbase-wc-kanban__card--drop-before",n),e.classList.toggle("designbase-wc-kanban__card--drop-after",r)})}getDropIndexFromPointer(e,t,a){const n=t.getBoundingClientRect();return e.clientY-n.top<n.height/2?a:a+1}getDropIndexFromColumnPointer(e,t){const a=Array.from(this.querySelectorAll(`.designbase-wc-kanban__column-body[data-column-id="${t}"] > .designbase-wc-kanban__card`));if(0===a.length)return 0;for(let t=0;t<a.length;t+=1){const n=a[t].getBoundingClientRect();if(e.clientY<n.top+n.height/2)return t}return a.length}commitDrop(){if(!this.dragState||!this.dropTarget||!this.isValidDropTarget())return void this.resetDragState();const{cardId:e}=this.dragState,{columnId:t,index:a}=this.dropTarget;this.resetDragState(),this.moveCard(e,t,a),this.render()}formatDueDate(e){const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleDateString("ko"===a()?"ko-KR":"en-US",{month:"short",day:"numeric"})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e.charAt(0)).join("").slice(0,2).toUpperCase()}createTag(e){const t=document.createElement("span");return t.className=["designbase-wc-kanban__tag",e.variant&&`designbase-wc-kanban__tag--${e.variant}`].filter(Boolean).join(" "),t.textContent=e.label,t}priorityLabel(e){return"ko"===a()?c[e]:{low:"Low",medium:"Medium",high:"High",urgent:"Urgent"}[e]}refreshLocale(){this.setAttribute("aria-label",e("칸반 보드")),this.querySelectorAll("[data-priority]").forEach(e=>{const t=e.dataset.priority,a=this.priorityLabel(t);e.textContent=a,e.setAttribute("aria-label",n("우선순위 {0}",[a]))}),this.getAttribute("empty-column-text")||this.querySelectorAll(".designbase-wc-kanban__column-empty").forEach(t=>{t.textContent=e("카드가 없습니다")}),this.querySelectorAll(".designbase-wc-kanban__add-card span").forEach(t=>{t.textContent=e("카드 추가")})}createPriorityBadge(e){const t=document.createElement("span");t.className=`designbase-wc-kanban__priority designbase-wc-kanban__priority--${e}`,t.dataset.priority=e;const a=this.priorityLabel(e);return t.textContent=a,t.setAttribute("aria-label",n("우선순위 {0}",[a])),t}createAssignee(e){const t=document.createElement("div");if(t.className="designbase-wc-kanban__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.className="designbase-wc-kanban__assignee-avatar",a.src=e.avatar,a.alt=e.name,t.append(a)}else{const a=document.createElement("span");a.className="designbase-wc-kanban__assignee-initials",a.textContent=this.getInitials(e),t.append(a)}const a=document.createElement("span");return a.className="designbase-wc-kanban__assignee-name",a.textContent=e.name,t.append(a),t}bindCardDrag(e,t,a,n,s,r){e.draggable=s&&!r&&!t.disabled,e.addEventListener("dragstart",e=>{!s||r||t.disabled||(this.dragState={cardId:t.id,columnId:a,cardIndex:n},this.dropTarget=null,e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",t.id)),this.classList.add("designbase-wc-kanban--dragging"),this.updateDragClasses())}),e.addEventListener("dragover",t=>{if(!this.dragState)return;t.preventDefault(),t.stopPropagation(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");if(!this.getBool("allow-cross-column",!0)&&this.dragState.columnId!==a)return;const s=this.getDropIndexFromPointer(t,e,n);this.setDropTarget({columnId:a,index:s})}),e.addEventListener("dragleave",t=>{const a=e.getBoundingClientRect(),n=t.clientX-a.left,s=t.clientY-a.top;(n<0||n>a.width||s<0||s>a.height)&&this.setDropTarget(null)}),e.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.commitDrop()}),e.addEventListener("dragend",()=>{this.resetDragState(),this.render()})}createCard(e,t,a,n){const r=document.createElement("article");r.className=["designbase-wc-kanban__card",e.disabled&&"designbase-wc-kanban__card--disabled",e.priority&&`designbase-wc-kanban__card--priority-${e.priority}`].filter(Boolean).join(" "),r.dataset.cardId=e.id,r.dataset.columnId=t,r.dataset.cardIndex=String(a),r.setAttribute("role","listitem"),r.tabIndex=e.disabled?-1:0;const d=document.createElement("div");d.className="designbase-wc-kanban__card-title-row";const i=document.createElement("h4");if(i.className="designbase-wc-kanban__card-title",i.textContent=e.title,d.append(i),e.priority&&o.includes(e.priority)&&d.append(this.createPriorityBadge(e.priority)),r.append(d),e.description){const t=document.createElement("p");t.className="designbase-wc-kanban__card-description",t.textContent=e.description,r.append(t)}if(e.tags?.length){const t=document.createElement("div");t.className="designbase-wc-kanban__card-tags",e.tags.forEach(e=>t.append(this.createTag(e))),r.append(t)}const c=document.createElement("div");if(c.className="designbase-wc-kanban__card-footer",e.assignee&&c.append(this.createAssignee(e.assignee)),e.dueDate){const t=document.createElement("span");t.className="designbase-wc-kanban__due-date",t.append(s("calendar","l"===n.size?12:"m"===n.size?11:10));const a=document.createElement("span");a.textContent=this.formatDueDate(e.dueDate),t.append(a),c.append(t)}return c.childNodes.length>0&&r.append(c),r.addEventListener("click",a=>{n.disabled||this.dispatchEvent(new CustomEvent("db-card-click",{detail:{card:e,columnId:t},bubbles:!0,composed:!0}))}),r.addEventListener("keydown",a=>{"Enter"!==a.key&&" "!==a.key||(a.preventDefault(),this.dispatchEvent(new CustomEvent("db-card-click",{detail:{card:e,columnId:t},bubbles:!0,composed:!0})))}),this.bindCardDrag(r,e,t,a,n.draggable,n.disabled),r}createColumn(t,a){const n=document.createElement("section"),r=void 0!==t.limit&&t.cards.length>t.limit;n.className=["designbase-wc-kanban__column",r&&"designbase-wc-kanban__column--over-limit"].filter(Boolean).join(" "),n.dataset.columnId=t.id,n.setAttribute("role","group"),n.setAttribute("aria-label",t.title);const d=document.createElement("header");d.className="designbase-wc-kanban__column-header";const i=document.createElement("div");if(i.className="designbase-wc-kanban__column-title-wrap",t.color){const e=document.createElement("span");e.className="designbase-wc-kanban__column-color",e.style.backgroundColor=t.color,e.setAttribute("aria-hidden","true"),i.append(e)}const o=document.createElement("h3");if(o.className="designbase-wc-kanban__column-title",o.textContent=t.title,i.append(o),d.append(i),a.showColumnCount){const e=document.createElement("span");e.className="designbase-wc-kanban__column-count",e.textContent=void 0!==t.limit?`${t.cards.length}/${t.limit}`:String(t.cards.length),d.append(e)}n.append(d);const c=document.createElement("div");if(c.className="designbase-wc-kanban__column-body",c.dataset.columnId=t.id,c.setAttribute("role","list"),c.addEventListener("dragover",e=>{if(!this.dragState)return;e.preventDefault(),e.stopPropagation(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");if(!this.getBool("allow-cross-column",!0)&&this.dragState.columnId!==t.id)return;const a=this.getDropIndexFromColumnPointer(e,t.id);this.setDropTarget({columnId:t.id,index:a})}),c.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.commitDrop()}),0===t.cards.length){const e=document.createElement("div");e.className="designbase-wc-kanban__column-empty",e.textContent=a.emptyColumnText,c.append(e)}else t.cards.forEach((e,n)=>{c.append(this.createCard(e,t.id,n,{size:a.size,draggable:a.draggable,disabled:a.disabled}))});if(n.append(c),a.showAddCard&&!a.disabled){const r=document.createElement("button");r.type="button",r.className="designbase-wc-kanban__add-card",r.append(s("plus","l"===a.size?14:"m"===a.size?12:10));const d=document.createElement("span");d.textContent=e("카드 추가"),r.append(d),r.disabled=this.getBool("disabled"),r.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-add-card",{detail:{columnId:t.id},bubbles:!0,composed:!0}))}),n.append(r)}return n}render(){const t=r(this.getAttribute("size"),i,"s"),a=this.getBool("disabled"),n=this.getBool("draggable",!0),s=this.getBool("show-column-count",!0),d=this.getBool("show-add-card"),o=this.getAttribute("empty-column-text")||e("카드가 없습니다");this.className=["designbase-wc-kanban",`designbase-wc-kanban--${t}`,this.getBool("full-width")&&"designbase-wc-kanban--full-width",a&&"designbase-wc-kanban--disabled",this.classList.contains("designbase-wc-kanban--dragging")&&"designbase-wc-kanban--dragging"].filter(Boolean).join(" ");const c=document.createElement("div");c.className="designbase-wc-kanban__board";const l=document.createDocumentFragment();this.columns.forEach(e=>{l.append(this.createColumn(e,{size:t,draggable:n,showColumnCount:s,showAddCard:d,emptyColumnText:o,disabled:a}))}),c.append(l),this.replaceChildren(c),this.updateDragClasses()}}customElements.get("db-kanban")||customElements.define("db-kanban",DbKanban);export{DbKanban};
@@ -7,6 +7,7 @@ interface DbLightboxImage {
7
7
  thumbnail?: string;
8
8
  }
9
9
  declare class DbLightbox extends HTMLElement {
10
+ private unsubscribeLocale?;
10
11
  private portalEl;
11
12
  private focusTrap?;
12
13
  /** 참조 카운트 스크롤락을 이 인스턴스가 잡고 있는지 (PERF-GLOBAL-STATE) */
@@ -38,6 +39,7 @@ declare class DbLightbox extends HTMLElement {
38
39
  private resetImageState;
39
40
  private close;
40
41
  private goTo;
42
+ private syncLocale;
41
43
  private ensureCarousel;
42
44
  private createIconButton;
43
45
  private buildPortal;
@@ -1 +1 @@
1
- import{inheritThemeScope as e}from"../core/theme-scope.js";import{dbText as t,dbFormat as s}from"../core/i18n.js";import{b as i}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js";import{createDbIcon as n}from"./db-icons.js";import{createFocusTrap as r}from"../core/focus-trap.js";import{lockScroll as a,unlockScroll as o}from"../core/scroll-lock.js";import{dbUid as l}from"../core/uid.js";import{LIGHTBOX_SIZES as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbLightbox extends HTMLElement{constructor(){super(...arguments),this.portalEl=null,this.scrollLocked=!1,this.titleId=l("db-lightbox-title"),this.imageEl=null,this.carouselViewport=null,this.slideSignature="",this.loadingEl=null,this.errorEl=null,this.counterBadge=null,this.prevNav=null,this.nextNav=null,this.currentIndex=0,this.imageLoaded=!1,this.imageError=!1,this.keydownHandler=null,this.boundSrc="",this.thumbnailSignature="",this.handleImageLoad=()=>{this.imageLoaded=!0,this.imageError=!1,this.syncImageLayers()},this.handleImageError=()=>{this.imageLoaded=!1,this.imageError=!0,this.syncImageLayers()}}static get observedAttributes(){return["images","current-index","size","open","enable-keyboard","show-thumbnails","show-counter","show-close-button","show-navigation-buttons","show-toolbar","close-on-backdrop-click","close-on-escape"]}connectedCallback(){this.classList.add("designbase-wc-lightbox-host"),this.syncOpenState()}disconnectedCallback(){this.unmount()}attributeChangedCallback(e,t,s){if("current-index"===e)return this.currentIndex=Number(s||0),this.resetImageState(),void(this.open&&(this.carouselEngine&&this.carouselEngine.getState().index!==this.currentIndex&&this.carouselEngine.goTo(this.currentIndex,"instant"),this.refreshView()));"open"!==e?"images"===e&&this.open&&this.refreshView():this.syncOpenState()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(e){e?this.setAttribute("open",""):this.removeAttribute("open")}parseImages(){const e=this.getAttribute("images");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}getCurrentImage(){return this.parseImages()[this.currentIndex]||null}resetImageState(){this.imageLoaded=!1,this.imageError=!1,this.boundSrc=""}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}goTo(e){this.carouselEngine?.goTo(e)}ensureCarousel(e){const s=this.carouselViewport;if(!s||!this.portalEl)return;const n=JSON.stringify(e.map(e=>[e.id,e.src]));if(this.carouselEngine&&n===this.slideSignature)return;this.carouselEngine?.destroy(),this.slideSignature=n,this.currentIndex=Math.max(0,Math.min(this.currentIndex,e.length-1)),this.resetImageState(),s.replaceChildren(),e.forEach((e,t)=>{const i=document.createElement("div");i.className="designbase-wc-lightbox__slide";const n=document.createElement("img");n.className="designbase-wc-lightbox__image",n.src=e.src,n.alt=e.alt||e.title||`이미지 ${t+1}`,n.draggable=!1,n.loading=t===this.currentIndex?"eager":"lazy",n.addEventListener("load",()=>{n.classList.add("designbase-wc-lightbox__image--loaded"),t===this.currentIndex&&this.handleImageLoad()}),n.addEventListener("error",()=>{t===this.currentIndex&&this.handleImageError()}),i.append(n),s.append(i)}),this.carouselEngine=i(s.parentElement,{startIndex:this.currentIndex,slidesPerView:1,gap:0,rewind:!0,keyboard:!1,label:t("이미지 갤러리")});const sync=()=>{const e=this.carouselEngine.getState().index;e!==this.currentIndex&&(this.currentIndex=e,this.setAttribute("current-index",String(e)),this.dispatchEvent(new CustomEvent("db-image-change",{detail:{index:e},bubbles:!0,composed:!0})))};this.carouselEngine.on("change",sync),this.carouselEngine.on("refresh",sync)}createIconButton(e,t,s,i,n={}){const r=document.createElement("db-button");return r.className=e,r.setAttribute("variant",n.variant||"ghost"),r.setAttribute("size",n.size||"m"),r.setAttribute("icon-only",""),r.setAttribute("start-icon",t),r.setAttribute("aria-label",s),n.radius&&r.setAttribute("radius",n.radius),r.addEventListener("db-click",i),r}buildPortal(){const e=this.getAttribute("size")||"l",s=c.includes(e)?e:"l",i=document.createElement("div");i.className=`designbase-wc-lightbox designbase-wc-lightbox--size-${s}`,i.setAttribute("data-wc-internal","");const r=document.createElement("div");r.className="designbase-wc-lightbox__overlay";const a=document.createElement("div");a.className="designbase-wc-lightbox__modal",a.setAttribute("role","dialog"),a.setAttribute("aria-modal","true"),a.setAttribute("aria-labelledby",this.titleId);const o=document.createElement("div");o.className="designbase-wc-lightbox__header";const l=document.createElement("div");l.className="designbase-wc-lightbox__title";const h=document.createElement("h3");h.className="designbase-wc-lightbox__title-text",h.id=this.titleId;const d=document.createElement("db-badge");d.className="designbase-wc-lightbox__counter",d.setAttribute("size","s"),d.setAttribute("variant","secondary"),d.setAttribute("type","text"),l.append(h,d);const u=document.createElement("div");u.className="designbase-wc-lightbox__header-actions","false"!==this.getAttribute("show-close-button")&&u.append(this.createIconButton("designbase-wc-lightbox__close-button","close","닫기",()=>this.close())),o.append(l,u);const g=document.createElement("div");g.className="designbase-wc-lightbox__content",this.prevNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--prev","chevron-left","이전 이미지",()=>this.carouselEngine?.prev(),{radius:"pill",size:"l"}),this.nextNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--next","chevron-right","다음 이미지",()=>this.carouselEngine?.next(),{radius:"pill",size:"l"});const b=document.createElement("div");b.className="designbase-wc-lightbox__image-container",this.errorEl=document.createElement("div"),this.errorEl.className="designbase-wc-lightbox__error",this.errorEl.hidden=!0;const m=n("gallery",24);m.classList.add("designbase-wc-lightbox__error-icon"),this.errorEl.append(m);const p=document.createElement("p");p.className="designbase-wc-lightbox__error-text",p.textContent=t("이미지를 불러올 수 없습니다"),this.errorEl.append(p),this.loadingEl=document.createElement("div"),this.loadingEl.className="designbase-wc-lightbox__loading";const E=document.createElement("db-spinner");E.setAttribute("type","circular"),E.setAttribute("size","m"),E.setAttribute("show-label",""),E.setAttribute("label","이미지 로딩 중..."),this.loadingEl.append(E),this.carouselViewport=document.createElement("div"),this.carouselViewport.className="designbase-wc-lightbox__viewport db-slide__viewport",b.append(this.carouselViewport,this.errorEl,this.loadingEl);const x=document.createElement("div");x.className="designbase-wc-lightbox__description";const w=document.createElement("p");w.className="designbase-wc-lightbox__description-text",x.append(w),"false"!==this.getAttribute("show-navigation-buttons")&&g.append(this.prevNav,this.nextNav),g.append(b,x);const _=document.createElement("div");_.className="designbase-wc-lightbox__thumbnails";const v=document.createElement("div");return v.className="designbase-wc-lightbox__thumbnails-container",_.append(v),a.append(o,g,_),r.append(a),i.append(r),r.addEventListener("click",e=>{e.target===r&&"false"!==this.getAttribute("close-on-backdrop-click")&&this.close()}),this.portalEl=i,this.counterBadge=d,i}syncImageLayers(){this.imageEl&&this.loadingEl&&this.errorEl&&(this.imageEl.classList.toggle("designbase-wc-lightbox__image--loaded",this.imageLoaded),this.loadingEl.hidden=this.imageLoaded||this.imageError,this.errorEl.hidden=!this.imageError,this.imageEl.hidden=this.imageError)}updateThumbnails(){if(!this.portalEl)return;const e=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails-container"),t=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails");if(!e||!t)return;const i=this.parseImages(),n="false"!==this.getAttribute("show-thumbnails")&&i.length>1;if(t.hidden=!n,!n)return e.replaceChildren(),void(this.thumbnailSignature="");const r=i.map(e=>e.thumbnail||e.src).join("|");r!==this.thumbnailSignature||e.childElementCount!==i.length?(this.thumbnailSignature=r,e.replaceChildren(),i.forEach((t,i)=>{const n=document.createElement("button");n.type="button",n.className=["designbase-wc-lightbox__thumbnail",i===this.currentIndex&&"designbase-wc-lightbox__thumbnail--active"].filter(Boolean).join(" "),n.title=t.title||s("이미지 {0}",[i+1]),n.setAttribute("aria-label",t.alt||t.title||`이미지 ${i+1}`),n.setAttribute("aria-current",i===this.currentIndex?"true":"false");const r=document.createElement("img");r.className="designbase-wc-lightbox__thumbnail-image",r.src=t.thumbnail||t.src,r.alt="",r.draggable=!1,r.loading="lazy",r.decoding="async",n.append(r),n.addEventListener("click",()=>this.goTo(i)),e.append(n)})):Array.from(e.children).forEach((e,t)=>{const s=e,i=t===this.currentIndex;s.classList.toggle("designbase-wc-lightbox__thumbnail--active",i),s.setAttribute("aria-current",i?"true":"false")})}loadCurrentImage(){if(this.imageEl=this.carouselViewport?.children[this.currentIndex]?.querySelector("img")||null,!this.imageEl)return;const e=this.getCurrentImage();if(!e?.src)return this.imageEl.removeAttribute("src"),this.resetImageState(),void this.syncImageLayers();this.boundSrc!==e.src&&(this.resetImageState(),this.boundSrc=e.src,this.imageEl.src=e.src,this.imageEl.alt=e.alt||e.title||`이미지 ${this.currentIndex+1}`,this.syncImageLayers(),this.imageEl.complete&&this.imageEl.naturalWidth>0&&this.handleImageLoad())}refreshView(){if(!this.portalEl)return;const e=this.parseImages();this.ensureCarousel(e);const t=this.getCurrentImage(),s=this.portalEl.querySelector(".designbase-wc-lightbox__title-text"),i=this.portalEl.querySelector(".designbase-wc-lightbox__description-text"),n=this.portalEl.querySelector(".designbase-wc-lightbox__description");if(s&&(s.textContent=t?.title||"",s.hidden=!t?.title),this.counterBadge){const t="false"!==this.getAttribute("show-counter")&&e.length>1?`${this.currentIndex+1} / ${e.length}`:"";this.counterBadge.textContent=t,this.counterBadge.hidden=!t}n&&i&&(i.textContent=t?.description||"",n.hidden=!t?.description);const r="false"!==this.getAttribute("show-navigation-buttons")&&e.length>1;this.prevNav&&(this.prevNav.hidden=!r),this.nextNav&&(this.nextNav.hidden=!r),this.loadCurrentImage(),this.updateThumbnails()}mount(){this.portalEl||(this.portalEl=this.buildPortal()),this.portalEl.isConnected||(e(this,this.portalEl),document.body.append(this.portalEl)),this.scrollLocked||(a(),this.scrollLocked=!0);const t=this.portalEl.querySelector(".designbase-wc-lightbox__modal");t&&!this.focusTrap&&(this.focusTrap=r(t),requestAnimationFrame(()=>this.focusTrap?.activate())),this.keydownHandler||(this.keydownHandler=e=>{this.open&&"false"!==this.getAttribute("enable-keyboard")&&("Escape"===e.key&&"false"!==this.getAttribute("close-on-escape")&&(e.preventDefault(),this.close()),"ArrowLeft"===e.key&&(e.preventDefault(),this.carouselEngine?.prev()),"ArrowRight"===e.key&&(e.preventDefault(),this.carouselEngine?.next()))},document.addEventListener("keydown",this.keydownHandler)),this.currentIndex=Number(this.getAttribute("current-index")||0),this.refreshView()}unmount(){this.carouselEngine?.destroy(),this.carouselEngine=void 0,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.portalEl?.remove(),this.scrollLocked&&(this.scrollLocked=!1,o()),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null)}syncOpenState(){this.open?this.mount():this.unmount()}}customElements.get("db-lightbox")||customElements.define("db-lightbox",DbLightbox);export{DbLightbox};
1
+ import{inheritThemeScope as e}from"../core/theme-scope.js";import{subscribeDbLocale as t,dbText as s,dbFormat as i}from"../core/i18n.js";import{b as n}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js";import{createDbIcon as r}from"./db-icons.js";import{createFocusTrap as a}from"../core/focus-trap.js";import{lockScroll as o,unlockScroll as l}from"../core/scroll-lock.js";import{dbUid as c}from"../core/uid.js";import{LIGHTBOX_SIZES as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbLightbox extends HTMLElement{constructor(){super(...arguments),this.portalEl=null,this.scrollLocked=!1,this.titleId=c("db-lightbox-title"),this.imageEl=null,this.carouselViewport=null,this.slideSignature="",this.loadingEl=null,this.errorEl=null,this.counterBadge=null,this.prevNav=null,this.nextNav=null,this.currentIndex=0,this.imageLoaded=!1,this.imageError=!1,this.keydownHandler=null,this.boundSrc="",this.thumbnailSignature="",this.handleImageLoad=()=>{this.imageLoaded=!0,this.imageError=!1,this.syncImageLayers()},this.handleImageError=()=>{this.imageLoaded=!1,this.imageError=!0,this.syncImageLayers()}}static get observedAttributes(){return["images","current-index","size","open","enable-keyboard","show-thumbnails","show-counter","show-close-button","show-navigation-buttons","show-toolbar","close-on-backdrop-click","close-on-escape"]}connectedCallback(){this.classList.add("designbase-wc-lightbox-host"),this.syncOpenState(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.syncLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.unmount()}attributeChangedCallback(e,t,s){if("current-index"===e)return this.currentIndex=Number(s||0),this.resetImageState(),void(this.open&&(this.carouselEngine&&this.carouselEngine.getState().index!==this.currentIndex&&this.carouselEngine.goTo(this.currentIndex,"instant"),this.refreshView()));"open"!==e?"images"===e&&this.open&&this.refreshView():this.syncOpenState()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(e){e?this.setAttribute("open",""):this.removeAttribute("open")}parseImages(){const e=this.getAttribute("images");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}getCurrentImage(){return this.parseImages()[this.currentIndex]||null}resetImageState(){this.imageLoaded=!1,this.imageError=!1,this.boundSrc=""}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}goTo(e){this.carouselEngine?.goTo(e)}syncLocale(){const e=this.portalEl;if(!e)return;e.querySelector(".designbase-wc-lightbox__close-button")?.setAttribute("aria-label",s("닫기")),this.prevNav?.setAttribute("aria-label",s("이전 이미지")),this.nextNav?.setAttribute("aria-label",s("다음 이미지"));const t=e.querySelector(".designbase-wc-lightbox__error-text");t&&(t.textContent=s("이미지를 불러올 수 없습니다")),this.loadingEl?.querySelector("db-spinner")?.setAttribute("label",s("이미지 로딩 중...")),this.carouselViewport?.parentElement?.setAttribute("aria-label",s("이미지 갤러리"));const n=this.parseImages();this.carouselViewport?.querySelectorAll("img.designbase-wc-lightbox__image").forEach((e,t)=>{const s=n[t];s&&e.setAttribute("alt",s.alt||s.title||i("이미지 {0}",[t+1]))}),e.querySelectorAll(".designbase-wc-lightbox__thumbnail").forEach((e,t)=>{const s=n[t];s&&(e.title=s.title||i("이미지 {0}",[t+1]),e.setAttribute("aria-label",s.alt||s.title||i("이미지 {0}",[t+1])))})}ensureCarousel(e){const t=this.carouselViewport;if(!t||!this.portalEl)return;const r=JSON.stringify(e.map(e=>[e.id,e.src]));if(this.carouselEngine&&r===this.slideSignature)return;this.carouselEngine?.destroy(),this.slideSignature=r,this.currentIndex=Math.max(0,Math.min(this.currentIndex,e.length-1)),this.resetImageState(),t.replaceChildren(),e.forEach((e,s)=>{const n=document.createElement("div");n.className="designbase-wc-lightbox__slide";const r=document.createElement("img");r.className="designbase-wc-lightbox__image",r.src=e.src,r.alt=e.alt||e.title||i("이미지 {0}",[s+1]),r.draggable=!1,r.loading=s===this.currentIndex?"eager":"lazy",r.addEventListener("load",()=>{r.classList.add("designbase-wc-lightbox__image--loaded"),s===this.currentIndex&&this.handleImageLoad()}),r.addEventListener("error",()=>{s===this.currentIndex&&this.handleImageError()}),n.append(r),t.append(n)}),this.carouselEngine=n(t.parentElement,{startIndex:this.currentIndex,slidesPerView:1,gap:0,rewind:!0,keyboard:!1,label:s("이미지 갤러리")});const sync=()=>{const e=this.carouselEngine.getState().index;e!==this.currentIndex&&(this.currentIndex=e,this.setAttribute("current-index",String(e)),this.dispatchEvent(new CustomEvent("db-image-change",{detail:{index:e},bubbles:!0,composed:!0})))};this.carouselEngine.on("change",sync),this.carouselEngine.on("refresh",sync)}createIconButton(e,t,s,i,n={}){const r=document.createElement("db-button");return r.className=e,r.setAttribute("variant",n.variant||"ghost"),r.setAttribute("size",n.size||"m"),r.setAttribute("icon-only",""),r.setAttribute("start-icon",t),r.setAttribute("aria-label",s),n.radius&&r.setAttribute("radius",n.radius),r.addEventListener("db-click",i),r}buildPortal(){const e=this.getAttribute("size")||"l",t=h.includes(e)?e:"l",i=document.createElement("div");i.className=`designbase-wc-lightbox designbase-wc-lightbox--size-${t}`,i.setAttribute("data-wc-internal","");const n=document.createElement("div");n.className="designbase-wc-lightbox__overlay";const a=document.createElement("div");a.className="designbase-wc-lightbox__modal",a.setAttribute("role","dialog"),a.setAttribute("aria-modal","true"),a.setAttribute("aria-labelledby",this.titleId);const o=document.createElement("div");o.className="designbase-wc-lightbox__header";const l=document.createElement("div");l.className="designbase-wc-lightbox__title";const c=document.createElement("h3");c.className="designbase-wc-lightbox__title-text",c.id=this.titleId;const d=document.createElement("db-badge");d.className="designbase-wc-lightbox__counter",d.setAttribute("size","s"),d.setAttribute("variant","secondary"),d.setAttribute("type","text"),l.append(c,d);const u=document.createElement("div");u.className="designbase-wc-lightbox__header-actions","false"!==this.getAttribute("show-close-button")&&u.append(this.createIconButton("designbase-wc-lightbox__close-button","close",s("닫기"),()=>this.close())),o.append(l,u);const g=document.createElement("div");g.className="designbase-wc-lightbox__content",this.prevNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--prev","chevron-left",s("이전 이미지"),()=>this.carouselEngine?.prev(),{radius:"pill",size:"l"}),this.nextNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--next","chevron-right",s("다음 이미지"),()=>this.carouselEngine?.next(),{radius:"pill",size:"l"});const b=document.createElement("div");b.className="designbase-wc-lightbox__image-container",this.errorEl=document.createElement("div"),this.errorEl.className="designbase-wc-lightbox__error",this.errorEl.hidden=!0;const m=r("gallery",24);m.classList.add("designbase-wc-lightbox__error-icon"),this.errorEl.append(m);const p=document.createElement("p");p.className="designbase-wc-lightbox__error-text",p.textContent=s("이미지를 불러올 수 없습니다"),this.errorEl.append(p),this.loadingEl=document.createElement("div"),this.loadingEl.className="designbase-wc-lightbox__loading";const E=document.createElement("db-spinner");E.setAttribute("type","circular"),E.setAttribute("size","m"),E.setAttribute("show-label",""),E.setAttribute("label",s("이미지 로딩 중...")),this.loadingEl.append(E),this.carouselViewport=document.createElement("div"),this.carouselViewport.className="designbase-wc-lightbox__viewport db-slide__viewport",b.append(this.carouselViewport,this.errorEl,this.loadingEl);const x=document.createElement("div");x.className="designbase-wc-lightbox__description";const _=document.createElement("p");_.className="designbase-wc-lightbox__description-text",x.append(_),"false"!==this.getAttribute("show-navigation-buttons")&&g.append(this.prevNav,this.nextNav),g.append(b,x);const w=document.createElement("div");w.className="designbase-wc-lightbox__thumbnails";const v=document.createElement("div");return v.className="designbase-wc-lightbox__thumbnails-container",w.append(v),a.append(o,g,w),n.append(a),i.append(n),n.addEventListener("click",e=>{e.target===n&&"false"!==this.getAttribute("close-on-backdrop-click")&&this.close()}),this.portalEl=i,this.counterBadge=d,i}syncImageLayers(){this.imageEl&&this.loadingEl&&this.errorEl&&(this.imageEl.classList.toggle("designbase-wc-lightbox__image--loaded",this.imageLoaded),this.loadingEl.hidden=this.imageLoaded||this.imageError,this.errorEl.hidden=!this.imageError,this.imageEl.hidden=this.imageError)}updateThumbnails(){if(!this.portalEl)return;const e=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails-container"),t=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails");if(!e||!t)return;const s=this.parseImages(),n="false"!==this.getAttribute("show-thumbnails")&&s.length>1;if(t.hidden=!n,!n)return e.replaceChildren(),void(this.thumbnailSignature="");const r=s.map(e=>e.thumbnail||e.src).join("|");r!==this.thumbnailSignature||e.childElementCount!==s.length?(this.thumbnailSignature=r,e.replaceChildren(),s.forEach((t,s)=>{const n=document.createElement("button");n.type="button",n.className=["designbase-wc-lightbox__thumbnail",s===this.currentIndex&&"designbase-wc-lightbox__thumbnail--active"].filter(Boolean).join(" "),n.title=t.title||i("이미지 {0}",[s+1]),n.setAttribute("aria-label",t.alt||t.title||i("이미지 {0}",[s+1])),n.setAttribute("aria-current",s===this.currentIndex?"true":"false");const r=document.createElement("img");r.className="designbase-wc-lightbox__thumbnail-image",r.src=t.thumbnail||t.src,r.alt="",r.draggable=!1,r.loading="lazy",r.decoding="async",n.append(r),n.addEventListener("click",()=>this.goTo(s)),e.append(n)})):Array.from(e.children).forEach((e,t)=>{const s=e,i=t===this.currentIndex;s.classList.toggle("designbase-wc-lightbox__thumbnail--active",i),s.setAttribute("aria-current",i?"true":"false")})}loadCurrentImage(){if(this.imageEl=this.carouselViewport?.children[this.currentIndex]?.querySelector("img")||null,!this.imageEl)return;const e=this.getCurrentImage();if(!e?.src)return this.imageEl.removeAttribute("src"),this.resetImageState(),void this.syncImageLayers();this.boundSrc!==e.src&&(this.resetImageState(),this.boundSrc=e.src,this.imageEl.src=e.src,this.imageEl.alt=e.alt||e.title||i("이미지 {0}",[this.currentIndex+1]),this.syncImageLayers(),this.imageEl.complete&&this.imageEl.naturalWidth>0&&this.handleImageLoad())}refreshView(){if(!this.portalEl)return;const e=this.parseImages();this.ensureCarousel(e);const t=this.getCurrentImage(),s=this.portalEl.querySelector(".designbase-wc-lightbox__title-text"),i=this.portalEl.querySelector(".designbase-wc-lightbox__description-text"),n=this.portalEl.querySelector(".designbase-wc-lightbox__description");if(s&&(s.textContent=t?.title||"",s.hidden=!t?.title),this.counterBadge){const t="false"!==this.getAttribute("show-counter")&&e.length>1?`${this.currentIndex+1} / ${e.length}`:"";this.counterBadge.textContent=t,this.counterBadge.hidden=!t}n&&i&&(i.textContent=t?.description||"",n.hidden=!t?.description);const r="false"!==this.getAttribute("show-navigation-buttons")&&e.length>1;this.prevNav&&(this.prevNav.hidden=!r),this.nextNav&&(this.nextNav.hidden=!r),this.loadCurrentImage(),this.updateThumbnails()}mount(){this.portalEl||(this.portalEl=this.buildPortal()),this.portalEl.isConnected||(e(this,this.portalEl),document.body.append(this.portalEl)),this.scrollLocked||(o(),this.scrollLocked=!0);const t=this.portalEl.querySelector(".designbase-wc-lightbox__modal");t&&!this.focusTrap&&(this.focusTrap=a(t),requestAnimationFrame(()=>this.focusTrap?.activate())),this.keydownHandler||(this.keydownHandler=e=>{this.open&&"false"!==this.getAttribute("enable-keyboard")&&("Escape"===e.key&&"false"!==this.getAttribute("close-on-escape")&&(e.preventDefault(),this.close()),"ArrowLeft"===e.key&&(e.preventDefault(),this.carouselEngine?.prev()),"ArrowRight"===e.key&&(e.preventDefault(),this.carouselEngine?.next()))},document.addEventListener("keydown",this.keydownHandler)),this.currentIndex=Number(this.getAttribute("current-index")||0),this.refreshView()}unmount(){this.carouselEngine?.destroy(),this.carouselEngine=void 0,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.portalEl?.remove(),this.scrollLocked&&(this.scrollLocked=!1,l()),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null)}syncOpenState(){this.open?this.mount():this.unmount()}}customElements.get("db-lightbox")||customElements.define("db-lightbox",DbLightbox);export{DbLightbox};
@@ -17,6 +17,7 @@ interface DbListItemData {
17
17
  }[];
18
18
  }
19
19
  declare class DbList extends HTMLElement {
20
+ private unsubscribeLocale?;
20
21
  static get observedAttributes(): string[];
21
22
  private groupName;
22
23
  get items(): DbListItemData[];
@@ -24,6 +25,7 @@ declare class DbList extends HTMLElement {
24
25
  get selectedItems(): string[];
25
26
  set selectedItems(value: string[] | string);
26
27
  connectedCallback(): void;
28
+ disconnectedCallback(): void;
27
29
  attributeChangedCallback(name: string): void;
28
30
  private flag;
29
31
  private controlSize;
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{dbUid as t}from"../core/uid.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{LIST_SIZES as i,LIST_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbList extends HTMLElement{constructor(){super(...arguments),this.groupName=t("db-list")}static get observedAttributes(){return["items","size","variant","layout","spacing","selectable","multiple","selected-items","empty-message","show-description","show-arrow","show-badge","loading","loading-count"]}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get selectedItems(){const e=this.getAttribute("selected-items")||"[]";try{const t=JSON.parse(e);return Array.isArray(t)?t.map(String):[]}catch{return[]}}set selectedItems(e){this.setAttribute("selected-items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.render()}attributeChangedCallback(e){this.isConnected&&("selected-items"!==e?this.render():this.syncSelectionState())}flag(e,t=!0){return this.hasAttribute(e)?"false"!==this.getAttribute(e):t}controlSize(){return"l"===s(this.getAttribute("size"),i,"m")?"m":"s"}parseBadge(e){return e?"string"==typeof e?{text:e,variant:"primary",style:"text"}:{text:e.text,variant:e.variant||"primary",style:e.style||"text"}:null}isSelected(e){return e.selected||this.selectedItems.includes(e.id)}setSelection(e){const t=JSON.stringify(e);this.getAttribute("selected-items")!==t?(this.setAttribute("selected-items",t),this.syncSelectionState(),this.dispatchEvent(new CustomEvent("db-select",{detail:{selectedItems:e},bubbles:!0,composed:!0}))):this.syncSelectionState()}toggleSelection(e){const t=this.hasAttribute("multiple"),s=this.selectedItems;let i;i=t?s.includes(e)?s.filter(t=>t!==e):[...s,e]:s.includes(e)?[]:[e],this.setSelection(i)}syncSelectionState(){const e=new Set(this.selectedItems);this.querySelectorAll(":scope > .designbase-wc-list__item").forEach(t=>{const s=t.dataset.itemId;if(!s)return;const i=e.has(s);t.classList.toggle("designbase-wc-list__item--selected",i),t.setAttribute("aria-selected",String(i));const n=t.querySelector("db-checkbox, db-radio");n&&(i?n.setAttribute("checked",""):n.removeAttribute("checked"))})}createSelectControl(e,t){const s=document.createElement("div");s.className="designbase-wc-list__item-select";const i=document.createElement(t?"db-checkbox":"db-radio");return i.setAttribute("has-label","false"),i.setAttribute("size",this.controlSize()),i.setAttribute("value",e.id),t||i.setAttribute("name",this.groupName),this.isSelected(e)&&i.setAttribute("checked",""),e.disabled&&i.setAttribute("disabled",""),i.addEventListener("click",e=>e.stopPropagation()),i.addEventListener("db-change",t=>{t.stopPropagation(),e.disabled||this.toggleSelection(e.id)}),s.append(i),s}createBadge(e){const t=document.createElement("db-badge");return t.setAttribute("size","s"),t.setAttribute("variant",e.variant),t.setAttribute("type",e.style),"number"===e.style?t.setAttribute("count",e.text):t.textContent=e.text,t}render(){const t=s(this.getAttribute("size"),i,"m"),a=s(this.getAttribute("variant"),n,"navigation"),c=this.getAttribute("layout")||"vertical",l=this.getAttribute("spacing")||"s",d=this.hasAttribute("selectable"),r=this.hasAttribute("multiple"),o=this.hasAttribute("loading");o?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy");const m=Number(this.getAttribute("loading-count")||3),b=this.flag("show-description",!1),g=this.flag("show-arrow",!0),u=this.flag("show-badge",!0),p=this.items,h="s"===t?16:"l"===t?24:20;if(this.className=["designbase-wc-list",`designbase-wc-list--size-${t}`,`designbase-wc-list--variant-${a}`,`designbase-wc-list--layout-${c}`,`designbase-wc-list--spacing-${l}`,d&&"designbase-wc-list--selectable",r&&"designbase-wc-list--multiple",o&&"designbase-wc-list--loading"].filter(Boolean).join(" "),this.replaceChildren(),o)for(let e=0;e<m;e+=1){const e=document.createElement("div");e.className="designbase-wc-list__item designbase-wc-list__item--loading",e.innerHTML='\n <div class="designbase-wc-list__item-skeleton">\n <div class="designbase-wc-list__item-skeleton-icon"></div>\n <div class="designbase-wc-list__item-skeleton-content">\n <div class="designbase-wc-list__item-skeleton-title"></div>\n <div class="designbase-wc-list__item-skeleton-description"></div>\n </div>\n </div>\n ',this.append(e)}else{if(0===p.length){const e=document.createElement("div");return e.className="designbase-wc-list__empty",e.textContent=this.getAttribute("empty-message")||"항목이 없습니다.",void this.append(e)}p.forEach((s,i)=>{const n=this.isSelected(s),o=b&&Boolean(s.description),m=Boolean(s.meta?.length),p=this.parseBadge(s.badge),_=Boolean(u&&p||g),w=document.createElement("div");if(w.className=["designbase-wc-list__item",`designbase-wc-list__item--size-${t}`,`designbase-wc-list__item--variant-${a}`,`designbase-wc-list__item--layout-${c}`,`designbase-wc-list__item--spacing-${l}`,n&&"designbase-wc-list__item--selected",s.disabled&&"designbase-wc-list__item--disabled",(d||!s.disabled)&&"designbase-wc-list__item--clickable",s.icon&&"designbase-wc-list__item--with-leading",(o||m)&&"designbase-wc-list__item--with-secondary",_&&"designbase-wc-list__item--with-trailing"].filter(Boolean).join(" "),w.dataset.itemId=s.id,w.tabIndex=s.disabled?-1:0,d&&w.setAttribute("aria-selected",String(n)),d&&w.append(this.createSelectControl(s,r)),s.icon){const t=document.createElement("div");t.className="designbase-wc-list__item-icon",t.append(e(s.icon,h)),w.append(t)}else if(s.image){const e=document.createElement("div");e.className="designbase-wc-list__item-image";const t=document.createElement("img");t.src=s.image,t.alt=s.title,e.append(t),w.append(e)}const v=document.createElement("div");v.className="designbase-wc-list__item-content";const A=document.createElement("div");A.className="designbase-wc-list__item-header";const y=document.createElement("h4");if(y.className="designbase-wc-list__item-title",y.textContent=s.title,A.append(y),v.append(A),o){const e=document.createElement("p");e.className="designbase-wc-list__item-description",e.textContent=s.description||"",v.append(e)}if(m&&s.meta){const e=document.createElement("div");e.className="designbase-wc-list__item-meta",s.meta.forEach(t=>{const s=document.createElement("div");s.className="designbase-wc-list__item-meta-item";const i=document.createElement("span");i.className="designbase-wc-list__item-meta-label",i.textContent=`${t.label}:`;const n=document.createElement("span");n.className="designbase-wc-list__item-meta-value",n.textContent=t.value,s.append(i,n),e.append(s)}),v.append(e)}if(w.append(v),_){const t=document.createElement("div");if(t.className="designbase-wc-list__item-trailing",u&&p&&t.append(this.createBadge(p)),g){const s=document.createElement("div");s.className="designbase-wc-list__item-arrow",s.setAttribute("aria-hidden","true"),s.append(e("chevron-right",16)),t.append(s)}w.append(t)}const handleActivate=()=>{s.disabled||(this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:s,index:i},bubbles:!0,composed:!0})),d&&this.toggleSelection(s.id))};w.addEventListener("click",handleActivate),w.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),handleActivate())}),this.append(w)})}}}customElements.get("db-list")||customElements.define("db-list",DbList);export{DbList};
1
+ import{createDbIcon as e}from"./db-icons.js";import{dbUid as t}from"../core/uid.js";import{subscribeDbLocale as s,dbText as i}from"../core/i18n.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{LIST_SIZES as a,LIST_VARIANTS as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbList extends HTMLElement{constructor(){super(...arguments),this.groupName=t("db-list")}static get observedAttributes(){return["items","size","variant","layout","spacing","selectable","multiple","selected-items","empty-message","show-description","show-arrow","show-badge","loading","loading-count"]}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get selectedItems(){const e=this.getAttribute("selected-items")||"[]";try{const t=JSON.parse(e);return Array.isArray(t)?t.map(String):[]}catch{return[]}}set selectedItems(e){this.setAttribute("selected-items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=s(()=>{const e=this.querySelector(".designbase-wc-list__empty");e&&(e.textContent=this.getAttribute("empty-message")||i("항목이 없습니다."))}),this.render()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(e){this.isConnected&&("selected-items"!==e?this.render():this.syncSelectionState())}flag(e,t=!0){return this.hasAttribute(e)?"false"!==this.getAttribute(e):t}controlSize(){return"l"===n(this.getAttribute("size"),a,"m")?"m":"s"}parseBadge(e){return e?"string"==typeof e?{text:e,variant:"primary",style:"text"}:{text:e.text,variant:e.variant||"primary",style:e.style||"text"}:null}isSelected(e){return e.selected||this.selectedItems.includes(e.id)}setSelection(e){const t=JSON.stringify(e);this.getAttribute("selected-items")!==t?(this.setAttribute("selected-items",t),this.syncSelectionState(),this.dispatchEvent(new CustomEvent("db-select",{detail:{selectedItems:e},bubbles:!0,composed:!0}))):this.syncSelectionState()}toggleSelection(e){const t=this.hasAttribute("multiple"),s=this.selectedItems;let i;i=t?s.includes(e)?s.filter(t=>t!==e):[...s,e]:s.includes(e)?[]:[e],this.setSelection(i)}syncSelectionState(){const e=new Set(this.selectedItems);this.querySelectorAll(":scope > .designbase-wc-list__item").forEach(t=>{const s=t.dataset.itemId;if(!s)return;const i=e.has(s);t.classList.toggle("designbase-wc-list__item--selected",i),t.setAttribute("aria-selected",String(i));const n=t.querySelector("db-checkbox, db-radio");n&&(i?n.setAttribute("checked",""):n.removeAttribute("checked"))})}createSelectControl(e,t){const s=document.createElement("div");s.className="designbase-wc-list__item-select";const i=document.createElement(t?"db-checkbox":"db-radio");return i.setAttribute("has-label","false"),i.setAttribute("size",this.controlSize()),i.setAttribute("value",e.id),t||i.setAttribute("name",this.groupName),this.isSelected(e)&&i.setAttribute("checked",""),e.disabled&&i.setAttribute("disabled",""),i.addEventListener("click",e=>e.stopPropagation()),i.addEventListener("db-change",t=>{t.stopPropagation(),e.disabled||this.toggleSelection(e.id)}),s.append(i),s}createBadge(e){const t=document.createElement("db-badge");return t.setAttribute("size","s"),t.setAttribute("variant",e.variant),t.setAttribute("type",e.style),"number"===e.style?t.setAttribute("count",e.text):t.textContent=e.text,t}render(){const t=n(this.getAttribute("size"),a,"m"),s=n(this.getAttribute("variant"),c,"navigation"),l=this.getAttribute("layout")||"vertical",d=this.getAttribute("spacing")||"s",r=this.hasAttribute("selectable"),o=this.hasAttribute("multiple"),m=this.hasAttribute("loading");m?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy");const b=Number(this.getAttribute("loading-count")||3),u=this.flag("show-description",!1),g=this.flag("show-arrow",!0),h=this.flag("show-badge",!0),p=this.items,_="s"===t?16:"l"===t?24:20;if(this.className=["designbase-wc-list",`designbase-wc-list--size-${t}`,`designbase-wc-list--variant-${s}`,`designbase-wc-list--layout-${l}`,`designbase-wc-list--spacing-${d}`,r&&"designbase-wc-list--selectable",o&&"designbase-wc-list--multiple",m&&"designbase-wc-list--loading"].filter(Boolean).join(" "),this.replaceChildren(),m)for(let e=0;e<b;e+=1){const e=document.createElement("div");e.className="designbase-wc-list__item designbase-wc-list__item--loading",e.innerHTML='\n <div class="designbase-wc-list__item-skeleton">\n <div class="designbase-wc-list__item-skeleton-icon"></div>\n <div class="designbase-wc-list__item-skeleton-content">\n <div class="designbase-wc-list__item-skeleton-title"></div>\n <div class="designbase-wc-list__item-skeleton-description"></div>\n </div>\n </div>\n ',this.append(e)}else{if(0===p.length){const e=document.createElement("div");return e.className="designbase-wc-list__empty",e.textContent=this.getAttribute("empty-message")||i("항목이 없습니다."),void this.append(e)}p.forEach((i,n)=>{const a=this.isSelected(i),c=u&&Boolean(i.description),m=Boolean(i.meta?.length),b=this.parseBadge(i.badge),p=Boolean(h&&b||g),w=document.createElement("div");if(w.className=["designbase-wc-list__item",`designbase-wc-list__item--size-${t}`,`designbase-wc-list__item--variant-${s}`,`designbase-wc-list__item--layout-${l}`,`designbase-wc-list__item--spacing-${d}`,a&&"designbase-wc-list__item--selected",i.disabled&&"designbase-wc-list__item--disabled",(r||!i.disabled)&&"designbase-wc-list__item--clickable",i.icon&&"designbase-wc-list__item--with-leading",(c||m)&&"designbase-wc-list__item--with-secondary",p&&"designbase-wc-list__item--with-trailing"].filter(Boolean).join(" "),w.dataset.itemId=i.id,w.tabIndex=i.disabled?-1:0,r&&w.setAttribute("aria-selected",String(a)),r&&w.append(this.createSelectControl(i,o)),i.icon){const t=document.createElement("div");t.className="designbase-wc-list__item-icon",t.append(e(i.icon,_)),w.append(t)}else if(i.image){const e=document.createElement("div");e.className="designbase-wc-list__item-image";const t=document.createElement("img");t.src=i.image,t.alt=i.title,e.append(t),w.append(e)}const v=document.createElement("div");v.className="designbase-wc-list__item-content";const A=document.createElement("div");A.className="designbase-wc-list__item-header";const y=document.createElement("h4");if(y.className="designbase-wc-list__item-title",y.textContent=i.title,A.append(y),v.append(A),c){const e=document.createElement("p");e.className="designbase-wc-list__item-description",e.textContent=i.description||"",v.append(e)}if(m&&i.meta){const e=document.createElement("div");e.className="designbase-wc-list__item-meta",i.meta.forEach(t=>{const s=document.createElement("div");s.className="designbase-wc-list__item-meta-item";const i=document.createElement("span");i.className="designbase-wc-list__item-meta-label",i.textContent=`${t.label}:`;const n=document.createElement("span");n.className="designbase-wc-list__item-meta-value",n.textContent=t.value,s.append(i,n),e.append(s)}),v.append(e)}if(w.append(v),p){const t=document.createElement("div");if(t.className="designbase-wc-list__item-trailing",h&&b&&t.append(this.createBadge(b)),g){const s=document.createElement("div");s.className="designbase-wc-list__item-arrow",s.setAttribute("aria-hidden","true"),s.append(e("chevron-right",16)),t.append(s)}w.append(t)}const handleActivate=()=>{i.disabled||(this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:i,index:n},bubbles:!0,composed:!0})),r&&this.toggleSelection(i.id))};w.addEventListener("click",handleActivate),w.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),handleActivate())}),this.append(w)})}}}customElements.get("db-list")||customElements.define("db-list",DbList);export{DbList};
@@ -1,6 +1,7 @@
1
1
  declare class DbMarkdownEditor extends HTMLElement {
2
2
  static get observedAttributes(): string[];
3
3
  private built;
4
+ private unsubscribeLocale?;
4
5
  private internalValue;
5
6
  private currentMode;
6
7
  private isFocused;
@@ -28,6 +29,7 @@ declare class DbMarkdownEditor extends HTMLElement {
28
29
  get value(): string;
29
30
  set value(next: string);
30
31
  private getBool;
32
+ private syncLocale;
31
33
  private syncFromAttributes;
32
34
  private updateRootClasses;
33
35
  private markdownToHtml;
@@ -1 +1 @@
1
- import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{sanitizeHtmlFragment as s}from"../core/safe-html.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARKDOWN_EDITOR_SIZES as l,MARKDOWN_EDITOR_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const o="designbase-wc-markdown-editor";class DbMarkdownEditor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.internalValue="",this.currentMode="preview",this.isFocused=!1,this.wordCount=0,this.lineCount=0,this.lastSaved=null,this.isSaving=!1,this.handleKeyDown=t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;const{ctrlKey:e,shiftKey:i,key:s}=t;e&&"b"===s?(t.preventDefault(),this.insertText("**","**","**")):e&&"i"===s?(t.preventDefault(),this.insertText("*","*","*")):e&&"k"===s?(t.preventDefault(),this.insertText("[","](",")")):e&&"`"===s?(t.preventDefault(),this.insertText("`","`","`")):e&&i&&"S"===s?(t.preventDefault(),this.insertText("~~","~~","~~")):"Tab"===s&&(t.preventDefault(),this.insertText(" ","",""))}}static get observedAttributes(){return["size","variant","mode","theme","value","placeholder","min-height","max-height","auto-height","readonly","disabled","show-toolbar","show-status","show-word-count","show-line-count","auto-save","auto-save-interval","file-upload"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.syncFromAttributes(),this.renderMode(),this.updateCounts(),this.updateStatus(),this.setupAutoSave()}disconnectedCallback(){this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer)}attributeChangedCallback(t){if(this.built){if("value"===t&&this.textareaEl)return this.internalValue=this.getAttribute("value")||"",this.textareaEl.value=this.internalValue,this.updatePreview(),this.updateCodeView(),void this.updateCounts();if("mode"===t)return this.currentMode=this.getAttribute("mode")||"preview",void this.renderMode();"auto-save"!==t&&"auto-save-interval"!==t||this.setupAutoSave(),this.updateRootClasses()}}get value(){return this.internalValue}set value(t){this.internalValue=t,this.setAttribute("value",t),this.textareaEl&&(this.textareaEl.value=t),this.updatePreview(),this.updateCodeView(),this.updateCounts()}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}syncFromAttributes(){if(this.internalValue=this.getAttribute("value")||"",this.currentMode=this.getAttribute("mode")||"preview",this.textareaEl){this.textareaEl.value=this.internalValue,this.textareaEl.placeholder=this.getAttribute("placeholder")||"마크다운을 입력하세요...",this.textareaEl.readOnly=this.getBool("readonly"),this.textareaEl.disabled=this.getBool("disabled");const t=Number(this.getAttribute("min-height")||200),e=Number(this.getAttribute("max-height")||600),i=this.getBool("auto-height");this.textareaEl.style.minHeight=i?"auto":`${t}px`,this.textareaEl.style.maxHeight=i?"none":`${e}px`}this.updateRootClasses(),this.updatePreview(),this.updateCodeView()}updateRootClasses(){const t=a(this.getAttribute("size"),l,"m"),e=a(this.getAttribute("variant"),n,"default"),i=this.getAttribute("theme")||"light";this.className=[o,`${o}--size-${t}`,`${o}--variant-${e}`,`${o}--mode-${this.currentMode}`,`${o}--theme-${i}`,this.isFocused&&`${o}--focused`,this.getBool("disabled")&&`${o}--disabled`,this.getBool("readonly")&&`${o}--readonly`].filter(Boolean).join(" ")}markdownToHtml(t){return t.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/~~(.*)~~/gim,"<del>$1</del>").replace(/`(.*)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/!\[([^\]]*)\]\(([^)]+)\)/gim,'<img alt="$1" src="$2" />').replace(/^> (.*$)/gim,"<blockquote>$1</blockquote>").replace(/^- (.*$)/gim,"<ul><li>$1</li></ul>").replace(/^(\d+)\. (.*$)/gim,"<ol><li>$2</li></ol>").replace(/\n/gim,"<br />")}updatePreview(){this.previewEl&&this.previewEl.replaceChildren(s(this.markdownToHtml(this.internalValue)))}updateCodeView(){if(this.codeViewEl){const t=this.codeViewEl.querySelector("code");t&&(t.textContent=this.internalValue)}}updateCounts(){this.wordCount=this.internalValue.trim()?this.internalValue.trim().split(/\s+/).length:0,this.lineCount=this.internalValue?this.internalValue.split("\n").length:0,this.wordCountEl&&(this.wordCountEl.textContent=t("단어: {0}",[this.wordCount])),this.lineCountEl&&(this.lineCountEl.textContent=t("라인: {0}",[this.lineCount]))}updateStatus(){if(!this.statusEl)return;const e=this.getBool("show-status",!0);this.statusEl.hidden=!e,this.wordCountEl&&(this.wordCountEl.hidden=!this.getBool("show-word-count",!0)),this.lineCountEl&&(this.lineCountEl.hidden=!this.getBool("show-line-count",!0)),this.lastSavedEl&&(this.lastSavedEl.hidden=!this.lastSaved,this.lastSaved&&(this.lastSavedEl.textContent=t("저장됨: {0}",[this.lastSaved.toLocaleTimeString()]))),this.savingEl&&(this.savingEl.hidden=!this.isSaving)}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.internalValue},bubbles:!0,composed:!0}))}insertText(t,e="",i=""){if(!this.textareaEl||this.getBool("disabled")||this.getBool("readonly"))return;const{selectionStart:s,selectionEnd:a}=this.textareaEl,l=this.internalValue.substring(s,a),n=e+(l||t)+i,o=this.internalValue.substring(0,s)+n+this.internalValue.substring(a);this.internalValue=o,this.textareaEl.value=o,this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts();const r=s+e.length+(l?l.length:t.length);window.setTimeout(()=>{this.textareaEl&&(this.textareaEl.setSelectionRange(r,r),this.textareaEl.focus())},0)}getDefaultToolbarActions(){return[{id:"bold",label:"B",tooltip:"굵게 (Ctrl+B)",shortcut:"Ctrl+B",action:()=>this.insertText("**","**","**")},{id:"italic",label:"I",tooltip:"기울임 (Ctrl+I)",shortcut:"Ctrl+I",action:()=>this.insertText("*","*","*")},{id:"strikethrough",label:"S",tooltip:"취소선 (Ctrl+Shift+S)",shortcut:"Ctrl+Shift+S",action:()=>this.insertText("~~","~~","~~")},{id:"separator1",label:"|",separator:!0,action:()=>{}},{id:"heading1",label:"H1",tooltip:"제목 1",action:()=>this.insertText("# ","","")},{id:"heading2",label:"H2",tooltip:"제목 2",action:()=>this.insertText("## ","","")},{id:"heading3",label:"H3",tooltip:"제목 3",action:()=>this.insertText("### ","","")},{id:"separator2",label:"|",separator:!0,action:()=>{}},{id:"link",label:"",icon:"share-alt",tooltip:"링크 (Ctrl+K)",shortcut:"Ctrl+K",action:()=>this.insertText("[","](",")")},{id:"image",label:"",icon:"video",tooltip:"이미지",action:()=>this.insertText("![","](",")")},{id:"code",label:"",icon:"code",tooltip:"인라인 코드 (Ctrl+`)",shortcut:"Ctrl+`",action:()=>this.insertText("`","`","`")},{id:"codeBlock",label:"```",tooltip:"코드 블록",action:()=>this.insertText("\n```\n","","\n```\n")},{id:"separator3",label:"|",separator:!0,action:()=>{}},{id:"list",label:"•",tooltip:"순서 없는 목록",action:()=>this.insertText("- ","","")},{id:"orderedList",label:"1.",tooltip:"순서 있는 목록",action:()=>this.insertText("1. ","","")},{id:"quote",label:'"',tooltip:"인용구",action:()=>this.insertText("> ","","")},{id:"separator4",label:"|",separator:!0,action:()=>{}},{id:"table",label:"⊞",tooltip:"테이블",action:()=>this.insertText("\n| 헤더1 | 헤더2 | 헤더3 |\n|-------|-------|-------|\n| 셀1 | 셀2 | 셀3 |\n","","")},{id:"horizontalRule",label:"—",tooltip:"수평선",action:()=>this.insertText("\n---\n","","")}]}renderToolbar(){if(!this.toolbarEl)return;const t=this.getBool("show-toolbar",!0);this.toolbarEl.hidden=!t,this.toolbarEl.replaceChildren();const s=document.createElement("div");s.className=`${o}__mode-buttons`;[{mode:"edit",icon:"write",title:e("편집 모드")},{mode:"preview",icon:"show",title:e("미리보기 모드")},{mode:"split",icon:"hide",title:e("분할 모드")},{mode:"code",icon:"code",title:e("코드 보기")}].forEach(({mode:t,icon:e,title:a})=>{const l=document.createElement("button");l.type="button",l.className=`${o}__mode-button${this.currentMode===t?` ${o}__mode-button--active`:""}`,l.title=a,l.append(i(e,16)),l.addEventListener("click",()=>{this.currentMode=t,this.updateRootClasses(),this.renderMode(),this.renderToolbar()}),s.append(l)}),this.toolbarEl.append(s);const a=document.createElement("div");if(a.className=`${o}__toolbar-separator`,this.toolbarEl.append(a),"code"!==this.currentMode&&(this.getDefaultToolbarActions().forEach(t=>{const e=document.createElement("button");if(e.type="button",e.className=`${o}__toolbar-item`,e.disabled=this.getBool("disabled"),t.tooltip&&(e.title=t.tooltip),t.icon)e.append(i(t.icon,16));else if("bold"===t.id){const i=document.createElement("strong");i.textContent=t.label,e.append(i)}else if("italic"===t.id){const i=document.createElement("em");i.textContent=t.label,e.append(i)}else if("strikethrough"===t.id){const i=document.createElement("span");i.style.textDecoration="line-through",i.textContent=t.label,e.append(i)}else e.textContent=t.label;if(t.shortcut){const i=document.createElement("span");i.className=`${o}__toolbar-shortcut`,i.textContent=t.shortcut,e.append(i)}e.addEventListener("click",t.action),this.toolbarEl?.append(e)}),this.getBool("file-upload"))){const t=document.createElement("label");t.className=`${o}__file-upload`;const e=document.createElement("input");e.type="file",e.accept="image/*",e.hidden=!0,e.addEventListener("change",async()=>{const t=e.files?.[0];if(!t)return;const i=new CustomEvent("db-file-upload",{detail:{file:t},bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(i),!i.defaultPrevented){const e=URL.createObjectURL(t);this.insertText(`![${t.name}](${e})`)}e.value=""}),t.append(e,i("upload",16)),this.toolbarEl.append(t)}}renderMode(){if(!this.editPanelEl||!this.previewPanelEl||!this.codePanelEl)return;const t="edit"===this.currentMode||"split"===this.currentMode,e="preview"===this.currentMode||"split"===this.currentMode,i="code"===this.currentMode;this.editPanelEl.hidden=!t,this.previewPanelEl.hidden=!e,this.codePanelEl.hidden=!i,this.updateRootClasses(),this.renderToolbar()}setupAutoSave(){if(this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer),!this.getBool("auto-save"))return;const t=Number(this.getAttribute("auto-save-interval")||3e4);this.autoSaveTimer=window.setInterval(()=>{const t=this.getAttribute("value")||"";this.internalValue&&this.internalValue!==t&&(this.isSaving=!0,this.updateStatus(),this.dispatchEvent(new CustomEvent("db-save",{detail:{value:this.internalValue},bubbles:!0,composed:!0})),this.isSaving=!1,this.lastSaved=new Date,this.updateStatus())},t)}build(){this.toolbarEl=document.createElement("div"),this.toolbarEl.className=`${o}__toolbar`,this.contentEl=document.createElement("div"),this.contentEl.className=`${o}__content`,this.editPanelEl=document.createElement("div"),this.editPanelEl.className=`${o}__edit-panel`,this.textareaEl=document.createElement("textarea"),this.textareaEl.className=`${o}__textarea`,this.textareaEl.addEventListener("input",()=>{this.internalValue=this.textareaEl?.value||"",this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts()}),this.textareaEl.addEventListener("focus",()=>{this.isFocused=!0,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("blur",()=>{this.isFocused=!1,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("keydown",this.handleKeyDown),this.editPanelEl.append(this.textareaEl),this.previewPanelEl=document.createElement("div"),this.previewPanelEl.className=`${o}__preview-panel`,this.previewEl=document.createElement("div"),this.previewEl.className=`${o}__preview`,this.previewPanelEl.append(this.previewEl),this.codePanelEl=document.createElement("div"),this.codePanelEl.className=`${o}__code-panel`,this.codeViewEl=document.createElement("pre"),this.codeViewEl.className=`${o}__code-view`;const t=document.createElement("code");this.codeViewEl.append(t),this.codePanelEl.append(this.codeViewEl),this.contentEl.append(this.editPanelEl,this.previewPanelEl,this.codePanelEl),this.statusEl=document.createElement("div"),this.statusEl.className=`${o}__status`,this.wordCountEl=document.createElement("span"),this.wordCountEl.className=`${o}__word-count`,this.lineCountEl=document.createElement("span"),this.lineCountEl.className=`${o}__line-count`,this.lastSavedEl=document.createElement("span"),this.lastSavedEl.className=`${o}__last-saved`,this.savingEl=document.createElement("span"),this.savingEl.className=`${o}__saving`,this.savingEl.textContent=e("저장 중..."),this.statusEl.append(this.wordCountEl,this.lineCountEl,this.lastSavedEl,this.savingEl),this.append(this.toolbarEl,this.contentEl,this.statusEl)}}customElements.get("db-markdown-editor")||customElements.define("db-markdown-editor",DbMarkdownEditor);export{DbMarkdownEditor};
1
+ import{subscribeDbLocale as t,dbText as e,dbFormat as i,getDbLocale as s}from"../core/i18n.js";import{createDbIcon as a}from"./db-icons.js";import{sanitizeHtmlFragment as l}from"../core/safe-html.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARKDOWN_EDITOR_SIZES as n,MARKDOWN_EDITOR_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const h="designbase-wc-markdown-editor";class DbMarkdownEditor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.internalValue="",this.currentMode="preview",this.isFocused=!1,this.wordCount=0,this.lineCount=0,this.lastSaved=null,this.isSaving=!1,this.handleKeyDown=t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;const{ctrlKey:e,shiftKey:i,key:s}=t;e&&"b"===s?(t.preventDefault(),this.insertText("**","**","**")):e&&"i"===s?(t.preventDefault(),this.insertText("*","*","*")):e&&"k"===s?(t.preventDefault(),this.insertText("[","](",")")):e&&"`"===s?(t.preventDefault(),this.insertText("`","`","`")):e&&i&&"S"===s?(t.preventDefault(),this.insertText("~~","~~","~~")):"Tab"===s&&(t.preventDefault(),this.insertText(" ","",""))}}static get observedAttributes(){return["size","variant","mode","theme","value","placeholder","min-height","max-height","auto-height","readonly","disabled","show-toolbar","show-status","show-word-count","show-line-count","auto-save","auto-save-interval","file-upload"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.syncFromAttributes(),this.renderMode(),this.updateCounts(),this.updateStatus(),this.setupAutoSave(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.syncLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer)}attributeChangedCallback(t){if(this.built){if("value"===t&&this.textareaEl)return this.internalValue=this.getAttribute("value")||"",this.textareaEl.value=this.internalValue,this.updatePreview(),this.updateCodeView(),void this.updateCounts();if("placeholder"===t&&this.textareaEl)this.textareaEl.placeholder=this.getAttribute("placeholder")||e("마크다운을 입력하세요...");else{if("mode"===t)return this.currentMode=this.getAttribute("mode")||"preview",void this.renderMode();"show-toolbar"===t&&this.toolbarEl&&(this.toolbarEl.hidden=!this.getBool("show-toolbar",!0)),["show-status","show-word-count","show-line-count"].includes(t)&&this.updateStatus(),"file-upload"===t&&this.renderToolbar(),"readonly"===t&&this.textareaEl&&(this.textareaEl.readOnly=this.getBool("readonly")),"disabled"===t&&this.textareaEl&&(this.textareaEl.disabled=this.getBool("disabled"),this.toolbarEl?.querySelectorAll(`.${h}__toolbar-item`).forEach(t=>{t.disabled=this.getBool("disabled")})),"auto-save"!==t&&"auto-save-interval"!==t||this.setupAutoSave(),this.updateRootClasses()}}}get value(){return this.internalValue}set value(t){this.internalValue=t,this.setAttribute("value",t),this.textareaEl&&(this.textareaEl.value=t),this.updatePreview(),this.updateCodeView(),this.updateCounts()}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}syncLocale(){this.textareaEl&&!this.getAttribute("placeholder")&&(this.textareaEl.placeholder=e("마크다운을 입력하세요...")),this.toolbarEl?.querySelectorAll("[data-locale-label]").forEach(t=>{const i=e(t.dataset.localeLabel||"");t.title=i,t.setAttribute("aria-label",i)}),this.toolbarEl?.querySelector(`.${h}__file-upload`)?.setAttribute("aria-label",e("이미지 업로드")),this.savingEl&&(this.savingEl.textContent=e("저장 중...")),this.updateCounts(),this.updateStatus()}syncFromAttributes(){if(this.internalValue=this.getAttribute("value")||"",this.currentMode=this.getAttribute("mode")||"preview",this.textareaEl){this.textareaEl.value=this.internalValue,this.textareaEl.placeholder=this.getAttribute("placeholder")||e("마크다운을 입력하세요..."),this.textareaEl.readOnly=this.getBool("readonly"),this.textareaEl.disabled=this.getBool("disabled");const t=Number(this.getAttribute("min-height")||200),i=Number(this.getAttribute("max-height")||600),s=this.getBool("auto-height");this.textareaEl.style.minHeight=s?"auto":`${t}px`,this.textareaEl.style.maxHeight=s?"none":`${i}px`}this.updateRootClasses(),this.updatePreview(),this.updateCodeView()}updateRootClasses(){const t=o(this.getAttribute("size"),n,"m"),e=o(this.getAttribute("variant"),r,"default"),i=this.getAttribute("theme")||"light";this.className=[h,`${h}--size-${t}`,`${h}--variant-${e}`,`${h}--mode-${this.currentMode}`,`${h}--theme-${i}`,this.isFocused&&`${h}--focused`,this.getBool("disabled")&&`${h}--disabled`,this.getBool("readonly")&&`${h}--readonly`].filter(Boolean).join(" ")}markdownToHtml(t){return t.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/~~(.*)~~/gim,"<del>$1</del>").replace(/`(.*)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/!\[([^\]]*)\]\(([^)]+)\)/gim,'<img alt="$1" src="$2" />').replace(/^> (.*$)/gim,"<blockquote>$1</blockquote>").replace(/^- (.*$)/gim,"<ul><li>$1</li></ul>").replace(/^(\d+)\. (.*$)/gim,"<ol><li>$2</li></ol>").replace(/\n/gim,"<br />")}updatePreview(){this.previewEl&&this.previewEl.replaceChildren(l(this.markdownToHtml(this.internalValue)))}updateCodeView(){if(this.codeViewEl){const t=this.codeViewEl.querySelector("code");t&&(t.textContent=this.internalValue)}}updateCounts(){this.wordCount=this.internalValue.trim()?this.internalValue.trim().split(/\s+/).length:0,this.lineCount=this.internalValue?this.internalValue.split("\n").length:0,this.wordCountEl&&(this.wordCountEl.textContent=i("단어: {0}",[this.wordCount])),this.lineCountEl&&(this.lineCountEl.textContent=i("라인: {0}",[this.lineCount]))}updateStatus(){if(!this.statusEl)return;const t=this.getBool("show-status",!0);this.statusEl.hidden=!t,this.wordCountEl&&(this.wordCountEl.hidden=!this.getBool("show-word-count",!0)),this.lineCountEl&&(this.lineCountEl.hidden=!this.getBool("show-line-count",!0)),this.lastSavedEl&&(this.lastSavedEl.hidden=!this.lastSaved,this.lastSaved&&(this.lastSavedEl.textContent=i("저장됨: {0}",[this.lastSaved.toLocaleTimeString("ko"===s()?"ko-KR":"en-US")]))),this.savingEl&&(this.savingEl.hidden=!this.isSaving)}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.internalValue},bubbles:!0,composed:!0}))}insertText(t,e="",i=""){if(!this.textareaEl||this.getBool("disabled")||this.getBool("readonly"))return;const{selectionStart:s,selectionEnd:a}=this.textareaEl,l=this.internalValue.substring(s,a),o=e+(l||t)+i,n=this.internalValue.substring(0,s)+o+this.internalValue.substring(a);this.internalValue=n,this.textareaEl.value=n,this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts();const r=s+e.length+(l?l.length:t.length);window.setTimeout(()=>{this.textareaEl&&(this.textareaEl.setSelectionRange(r,r),this.textareaEl.focus())},0)}getDefaultToolbarActions(){return[{id:"bold",label:"B",tooltip:"굵게 (Ctrl+B)",shortcut:"Ctrl+B",action:()=>this.insertText("**","**","**")},{id:"italic",label:"I",tooltip:"기울임 (Ctrl+I)",shortcut:"Ctrl+I",action:()=>this.insertText("*","*","*")},{id:"strikethrough",label:"S",tooltip:"취소선 (Ctrl+Shift+S)",shortcut:"Ctrl+Shift+S",action:()=>this.insertText("~~","~~","~~")},{id:"separator1",label:"|",separator:!0,action:()=>{}},{id:"heading1",label:"H1",tooltip:"제목 1",action:()=>this.insertText("# ","","")},{id:"heading2",label:"H2",tooltip:"제목 2",action:()=>this.insertText("## ","","")},{id:"heading3",label:"H3",tooltip:"제목 3",action:()=>this.insertText("### ","","")},{id:"separator2",label:"|",separator:!0,action:()=>{}},{id:"link",label:"",icon:"share-alt",tooltip:"링크 (Ctrl+K)",shortcut:"Ctrl+K",action:()=>this.insertText("[","](",")")},{id:"image",label:"",icon:"video",tooltip:"이미지",action:()=>this.insertText("![","](",")")},{id:"code",label:"",icon:"code",tooltip:"인라인 코드 (Ctrl+`)",shortcut:"Ctrl+`",action:()=>this.insertText("`","`","`")},{id:"codeBlock",label:"```",tooltip:"코드 블록",action:()=>this.insertText("\n```\n","","\n```\n")},{id:"separator3",label:"|",separator:!0,action:()=>{}},{id:"list",label:"•",tooltip:"순서 없는 목록",action:()=>this.insertText("- ","","")},{id:"orderedList",label:"1.",tooltip:"순서 있는 목록",action:()=>this.insertText("1. ","","")},{id:"quote",label:'"',tooltip:"인용구",action:()=>this.insertText("> ","","")},{id:"separator4",label:"|",separator:!0,action:()=>{}},{id:"table",label:"⊞",tooltip:"테이블",action:()=>this.insertText(e("\n| 헤더1 | 헤더2 | 헤더3 |\n|-------|-------|-------|\n| 셀1 | 셀2 | 셀3 |\n"),"","")},{id:"horizontalRule",label:"—",tooltip:"수평선",action:()=>this.insertText("\n---\n","","")}]}renderToolbar(){if(!this.toolbarEl)return;const t=this.getBool("show-toolbar",!0);this.toolbarEl.hidden=!t,this.toolbarEl.replaceChildren();const i=document.createElement("div");i.className=`${h}__mode-buttons`;[{mode:"edit",icon:"write",title:"편집 모드"},{mode:"preview",icon:"show",title:"미리보기 모드"},{mode:"split",icon:"hide",title:"분할 모드"},{mode:"code",icon:"code",title:"코드 보기"}].forEach(({mode:t,icon:s,title:l})=>{const o=document.createElement("button");o.type="button",o.className=`${h}__mode-button${this.currentMode===t?` ${h}__mode-button--active`:""}`,o.dataset.localeLabel=l,o.title=e(l),o.setAttribute("aria-label",e(l)),o.append(a(s,16)),o.addEventListener("click",()=>{this.currentMode=t,this.updateRootClasses(),this.renderMode(),this.renderToolbar()}),i.append(o)}),this.toolbarEl.append(i);const s=document.createElement("div");if(s.className=`${h}__toolbar-separator`,this.toolbarEl.append(s),"code"!==this.currentMode&&(this.getDefaultToolbarActions().forEach(t=>{const i=document.createElement("button");if(i.type="button",i.className=`${h}__toolbar-item`,i.disabled=this.getBool("disabled"),t.tooltip&&(i.dataset.localeLabel=t.tooltip,i.title=e(t.tooltip),i.setAttribute("aria-label",e(t.tooltip))),t.icon)i.append(a(t.icon,16));else if("bold"===t.id){const e=document.createElement("strong");e.textContent=t.label,i.append(e)}else if("italic"===t.id){const e=document.createElement("em");e.textContent=t.label,i.append(e)}else if("strikethrough"===t.id){const e=document.createElement("span");e.style.textDecoration="line-through",e.textContent=t.label,i.append(e)}else i.textContent=t.label;if(t.shortcut){const e=document.createElement("span");e.className=`${h}__toolbar-shortcut`,e.textContent=t.shortcut,i.append(e)}i.addEventListener("click",t.action),this.toolbarEl?.append(i)}),this.getBool("file-upload"))){const t=document.createElement("label");t.className=`${h}__file-upload`,t.setAttribute("aria-label",e("이미지 업로드"));const i=document.createElement("input");i.type="file",i.accept="image/*",i.hidden=!0,i.addEventListener("change",async()=>{const t=i.files?.[0];if(!t)return;const e=new CustomEvent("db-file-upload",{detail:{file:t},bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(e),!e.defaultPrevented){const e=URL.createObjectURL(t);this.insertText(`![${t.name}](${e})`)}i.value=""}),t.append(i,a("upload",16)),this.toolbarEl.append(t)}}renderMode(){if(!this.editPanelEl||!this.previewPanelEl||!this.codePanelEl)return;const t="edit"===this.currentMode||"split"===this.currentMode,e="preview"===this.currentMode||"split"===this.currentMode,i="code"===this.currentMode;this.editPanelEl.hidden=!t,this.previewPanelEl.hidden=!e,this.codePanelEl.hidden=!i,this.updateRootClasses(),this.renderToolbar()}setupAutoSave(){if(this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer),!this.getBool("auto-save"))return;const t=Number(this.getAttribute("auto-save-interval")||3e4);this.autoSaveTimer=window.setInterval(()=>{const t=this.getAttribute("value")||"";this.internalValue&&this.internalValue!==t&&(this.isSaving=!0,this.updateStatus(),this.dispatchEvent(new CustomEvent("db-save",{detail:{value:this.internalValue},bubbles:!0,composed:!0})),this.isSaving=!1,this.lastSaved=new Date,this.updateStatus())},t)}build(){this.toolbarEl=document.createElement("div"),this.toolbarEl.className=`${h}__toolbar`,this.contentEl=document.createElement("div"),this.contentEl.className=`${h}__content`,this.editPanelEl=document.createElement("div"),this.editPanelEl.className=`${h}__edit-panel`,this.textareaEl=document.createElement("textarea"),this.textareaEl.className=`${h}__textarea`,this.textareaEl.addEventListener("input",()=>{this.internalValue=this.textareaEl?.value||"",this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts()}),this.textareaEl.addEventListener("focus",()=>{this.isFocused=!0,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("blur",()=>{this.isFocused=!1,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("keydown",this.handleKeyDown),this.editPanelEl.append(this.textareaEl),this.previewPanelEl=document.createElement("div"),this.previewPanelEl.className=`${h}__preview-panel`,this.previewEl=document.createElement("div"),this.previewEl.className=`${h}__preview`,this.previewPanelEl.append(this.previewEl),this.codePanelEl=document.createElement("div"),this.codePanelEl.className=`${h}__code-panel`,this.codeViewEl=document.createElement("pre"),this.codeViewEl.className=`${h}__code-view`;const t=document.createElement("code");this.codeViewEl.append(t),this.codePanelEl.append(this.codeViewEl),this.contentEl.append(this.editPanelEl,this.previewPanelEl,this.codePanelEl),this.statusEl=document.createElement("div"),this.statusEl.className=`${h}__status`,this.wordCountEl=document.createElement("span"),this.wordCountEl.className=`${h}__word-count`,this.lineCountEl=document.createElement("span"),this.lineCountEl.className=`${h}__line-count`,this.lastSavedEl=document.createElement("span"),this.lastSavedEl.className=`${h}__last-saved`,this.savingEl=document.createElement("span"),this.savingEl.className=`${h}__saving`,this.savingEl.textContent=e("저장 중..."),this.statusEl.append(this.wordCountEl,this.lineCountEl,this.lastSavedEl,this.savingEl),this.append(this.toolbarEl,this.contentEl,this.statusEl)}}customElements.get("db-markdown-editor")||customElements.define("db-markdown-editor",DbMarkdownEditor);export{DbMarkdownEditor};
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{sanitizeHref as t}from"../core/safe-url.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MENU_ITEM_SIZES as n,MENU_ITEM_VARIANTS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbMenuItem extends HTMLElement{constructor(){super(...arguments),this.childrenId="db-menu-children-"+ ++DbMenuItem.nextId}static get observedAttributes(){return["label","href","icon","active","disabled","badge","badge-color","size","variant","type","menu-style","expanded","expandable","sub-items","depth"]}get subItems(){try{return JSON.parse(this.getAttribute("sub-items")||"[]")}catch{return[]}}set subItems(e){this.setAttribute("sub-items","string"==typeof e?e:JSON.stringify(e))}get expanded(){return this.hasAttribute("expanded")}set expanded(e){this.toggleAttribute("expanded",e)}connectedCallback(){this.render()}iconSize(e){return"s"===e?16:"l"===e?24:16}render(){const d=this.getAttribute("label")||"",a=t(this.getAttribute("href"),""),r=this.getAttribute("icon"),c=i(this.getAttribute("size"),n,"m"),b=i(this.getAttribute("variant"),s,"default"),u=this.getAttribute("type")||"block",o=this.getAttribute("menu-style")||"accordion",m=Number(this.getAttribute("depth")||0),l=this.hasAttribute("active"),h=this.hasAttribute("disabled"),p=(this.getAttribute("badge")||"").trim(),g=this.getAttribute("badge-color")||"primary",A=this.subItems,w=A.length>0,x=this.hasAttribute("expandable")||w,v=this.expanded,_=this.iconSize(c),f="accordion"===o&&w;this.className=["designbase-wc-menu-item",`designbase-wc-menu-item--${u}`,`designbase-wc-menu-item--${c}`,`designbase-wc-menu-item--${b}`,`designbase-wc-menu-item--${o}`,`designbase-wc-menu-item--depth-${m}`,l&&"designbase-wc-menu-item--active",h&&"designbase-wc-menu-item--disabled",x&&"designbase-wc-menu-item--expandable",v&&"designbase-wc-menu-item--expanded",w&&"designbase-wc-menu-item--with-children",p&&"designbase-wc-menu-item--with-badge",r&&"designbase-wc-menu-item--with-icon"].filter(Boolean).join(" "),this.replaceChildren();const y=document.createElement("button");if(y.type="button",y.title=d,y.disabled=h,l&&y.setAttribute("aria-current","page"),w&&(y.setAttribute("aria-expanded",String(v)),(f||v)&&y.setAttribute("aria-controls",this.childrenId)),y.addEventListener("keydown",e=>{w&&!h&&("ArrowRight"===e.key&&!this.expanded||"ArrowLeft"===e.key&&this.expanded)&&(e.preventDefault(),y.click())}),y.className=["designbase-wc-menu-item__content","designbase-wc-menu-item__content--clickable"].join(" "),r){const t=document.createElement("div");t.className=["designbase-wc-menu-item__icon",`designbase-wc-menu-item__icon--${b}`,l&&"designbase-wc-menu-item__icon--active",h&&"designbase-wc-menu-item__icon--disabled"].filter(Boolean).join(" "),t.append(e(r,_)),y.append(t)}const E=document.createElement("span");if(E.className="designbase-wc-menu-item__label",E.textContent=d,y.append(E),p){const e=document.createElement("db-badge");e.setAttribute("size","s"),e.setAttribute("variant",g),Number.isFinite(Number(p))?(e.setAttribute("type","number"),e.setAttribute("count",p),e.setAttribute("max-count","999")):(e.setAttribute("type","text"),e.textContent=p),y.append(e)}if(w){const t=document.createElement("div");t.className="designbase-wc-menu-item__expand-icon",t.append(e(v?"chevron-up":"chevron-down",16)),y.append(t)}if(y.addEventListener("click",e=>{h||(w&&x?(e.preventDefault(),this.expanded=!this.expanded):a&&(window.location.href=a),this.dispatchEvent(new CustomEvent("db-click",{detail:{label:d,href:a,expanded:this.expanded},bubbles:!0,composed:!0})))}),this.append(y),w&&(v||f)){const e=document.createElement("div");e.className=`designbase-wc-menu-item__children designbase-wc-menu-item__children--${o}`,e.id=this.childrenId,e.inert=!v||h,f&&e.setAttribute("aria-hidden",v?"false":"true"),A.forEach(i=>{const n=document.createElement("db-menu-item");n.setAttribute("label",i.label),n.setAttribute("type","block"),n.setAttribute("menu-style",o),n.setAttribute("size",c),n.setAttribute("depth",String(m+1));const s=t(i.href,"");s&&n.setAttribute("href",s),i.icon&&n.setAttribute("icon",i.icon),i.active&&n.setAttribute("active",""),i.disabled&&n.setAttribute("disabled",""),void 0!==i.badge&&n.setAttribute("badge",String(i.badge)),i.badgeColor&&n.setAttribute("badge-color",i.badgeColor),i.variant&&n.setAttribute("variant",i.variant),n.addEventListener("db-click",e=>{e.stopPropagation(),i.disabled||this.dispatchEvent(new CustomEvent("db-child-click",{detail:{child:i},bubbles:!0,composed:!0}))}),e.append(n)}),this.append(e)}}attributeChangedCallback(e){this.isConnected&&("expanded"!==e||"accordion"!==this.getAttribute("menu-style")?this.render():this.syncExpandedState())}syncExpandedState(){const t=this.expanded;this.classList.toggle("designbase-wc-menu-item--expanded",t),this.querySelector(":scope > .designbase-wc-menu-item__content")?.setAttribute("aria-expanded",String(t));const i=this.querySelector(".designbase-wc-menu-item__expand-icon");i&&i.replaceChildren(e(t?"chevron-up":"chevron-down",16));const n=this.querySelector(".designbase-wc-menu-item__children--accordion");n?(n.inert=!t||this.hasAttribute("disabled"),n.setAttribute("aria-hidden",t?"false":"true")):t&&this.subItems.length&&this.render()}}DbMenuItem.nextId=0,customElements.get("db-menu-item")||customElements.define("db-menu-item",DbMenuItem);export{DbMenuItem};
1
+ import{createDbIcon as e}from"./db-icons.js";import{sanitizeHref as t}from"../core/safe-url.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MENU_ITEM_SIZES as n,MENU_ITEM_VARIANTS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbMenuItem extends HTMLElement{constructor(){super(...arguments),this.childrenId="db-menu-children-"+ ++DbMenuItem.nextId}static get observedAttributes(){return["label","href","icon","active","disabled","badge","badge-color","size","variant","type","menu-style","expanded","expandable","split-expand","sub-items","depth"]}get subItems(){try{return JSON.parse(this.getAttribute("sub-items")||"[]")}catch{return[]}}set subItems(e){this.setAttribute("sub-items","string"==typeof e?e:JSON.stringify(e))}get expanded(){return this.hasAttribute("expanded")}set expanded(e){this.toggleAttribute("expanded",e)}connectedCallback(){this.render()}iconSize(e){return"s"===e?16:"l"===e?24:16}render(){const a=this.getAttribute("label")||"",d=t(this.getAttribute("href"),""),r=this.getAttribute("icon"),c=i(this.getAttribute("size"),n,"m"),b=i(this.getAttribute("variant"),s,"default"),u=this.getAttribute("type")||"block",o=this.getAttribute("menu-style")||"accordion",m=Number(this.getAttribute("depth")||0),l=this.hasAttribute("active"),h=this.hasAttribute("disabled"),p=(this.getAttribute("badge")||"").trim(),g=this.getAttribute("badge-color")||"primary",A=this.subItems,w=A.length>0,x=this.hasAttribute("expandable")||w,v=this.expanded,_=w&&!!d&&this.hasAttribute("split-expand"),f=this.iconSize(c),E="accordion"===o&&w;this.className=["designbase-wc-menu-item",`designbase-wc-menu-item--${u}`,`designbase-wc-menu-item--${c}`,`designbase-wc-menu-item--${b}`,`designbase-wc-menu-item--${o}`,`designbase-wc-menu-item--depth-${m}`,l&&"designbase-wc-menu-item--active",h&&"designbase-wc-menu-item--disabled",x&&"designbase-wc-menu-item--expandable",v&&"designbase-wc-menu-item--expanded",w&&"designbase-wc-menu-item--with-children",p&&"designbase-wc-menu-item--with-badge",r&&"designbase-wc-menu-item--with-icon"].filter(Boolean).join(" "),this.replaceChildren();const y=document.createElement(_?"a":"button");if(y instanceof HTMLButtonElement?y.type="button":h||(y.href=d),y.title=a,y instanceof HTMLButtonElement?y.disabled=h:h&&y.setAttribute("aria-disabled","true"),l&&y.setAttribute("aria-current","page"),w&&!_&&(y.setAttribute("aria-expanded",String(v)),(E||v)&&y.setAttribute("aria-controls",this.childrenId)),y.addEventListener("keydown",e=>{!w||h||_||("ArrowRight"===e.key&&!this.expanded||"ArrowLeft"===e.key&&this.expanded)&&(e.preventDefault(),y.click())}),y.className=["designbase-wc-menu-item__content","designbase-wc-menu-item__content--clickable"].join(" "),r){const t=document.createElement("div");t.className=["designbase-wc-menu-item__icon",`designbase-wc-menu-item__icon--${b}`,l&&"designbase-wc-menu-item__icon--active",h&&"designbase-wc-menu-item__icon--disabled"].filter(Boolean).join(" "),t.append(e(r,f)),y.append(t)}const k=document.createElement("span");if(k.className="designbase-wc-menu-item__label",k.textContent=a,y.append(k),p){const e=document.createElement("db-badge");e.setAttribute("size","s"),e.setAttribute("variant",g),Number.isFinite(Number(p))?(e.setAttribute("type","number"),e.setAttribute("count",p),e.setAttribute("max-count","999")):(e.setAttribute("type","text"),e.textContent=p),y.append(e)}if(w&&!_){const t=document.createElement("div");t.className="designbase-wc-menu-item__expand-icon",t.append(e(v?"chevron-up":"chevron-down",16)),y.append(t)}if(y.addEventListener("click",e=>{if(h)e.preventDefault();else{if(_){const t=new CustomEvent("db-navigate",{detail:{label:a,href:d},bubbles:!0,composed:!0,cancelable:!0});return void(this.dispatchEvent(t)||e.preventDefault())}w&&x?(e.preventDefault(),this.expanded=!this.expanded):d&&(window.location.href=d),this.dispatchEvent(new CustomEvent("db-click",{detail:{label:a,href:d,expanded:this.expanded},bubbles:!0,composed:!0}))}}),_){const t=document.createElement("div");t.className="designbase-wc-menu-item__split-row";const i=document.createElement("button");i.type="button",i.className="designbase-wc-menu-item__expand-icon designbase-wc-menu-item__expand-toggle",i.disabled=h,i.setAttribute("aria-label",a),i.setAttribute("aria-expanded",String(v)),i.setAttribute("aria-controls",this.childrenId),i.append(e(v?"chevron-up":"chevron-down",16)),i.addEventListener("click",()=>{h||(this.expanded=!this.expanded,this.dispatchEvent(new CustomEvent("db-click",{detail:{label:a,href:d,expanded:this.expanded},bubbles:!0,composed:!0})))}),t.append(y,i),this.append(t)}else this.append(y);if(w&&(v||E)){const e=document.createElement("div");e.className=`designbase-wc-menu-item__children designbase-wc-menu-item__children--${o}`,e.id=this.childrenId,e.inert=!v||h,E&&e.setAttribute("aria-hidden",v?"false":"true"),A.forEach(i=>{const n=document.createElement("db-menu-item");n.setAttribute("label",i.label),n.setAttribute("type","block"),n.setAttribute("menu-style",o),n.setAttribute("size",c),n.setAttribute("depth",String(m+1));const s=t(i.href,"");s&&n.setAttribute("href",s),i.icon&&n.setAttribute("icon",i.icon),i.active&&n.setAttribute("active",""),i.disabled&&n.setAttribute("disabled",""),void 0!==i.badge&&n.setAttribute("badge",String(i.badge)),i.badgeColor&&n.setAttribute("badge-color",i.badgeColor),i.variant&&n.setAttribute("variant",i.variant),n.addEventListener("db-click",e=>{e.stopPropagation(),i.disabled||this.dispatchEvent(new CustomEvent("db-child-click",{detail:{child:i},bubbles:!0,composed:!0}))}),e.append(n)}),this.append(e)}}attributeChangedCallback(e){this.isConnected&&("expanded"!==e||"accordion"!==this.getAttribute("menu-style")?this.render():this.syncExpandedState())}syncExpandedState(){const t=this.expanded;this.classList.toggle("designbase-wc-menu-item--expanded",t),this.querySelector(this.hasAttribute("split-expand")?":scope > .designbase-wc-menu-item__split-row > .designbase-wc-menu-item__expand-toggle":":scope > .designbase-wc-menu-item__content")?.setAttribute("aria-expanded",String(t));const i=this.querySelector(".designbase-wc-menu-item__expand-icon");i&&i.replaceChildren(e(t?"chevron-up":"chevron-down",16));const n=this.querySelector(".designbase-wc-menu-item__children--accordion");n?(n.inert=!t||this.hasAttribute("disabled"),n.setAttribute("aria-hidden",t?"false":"true")):t&&this.subItems.length&&this.render()}}DbMenuItem.nextId=0,customElements.get("db-menu-item")||customElements.define("db-menu-item",DbMenuItem);export{DbMenuItem};
@@ -44,6 +44,8 @@ interface DbNavbarUserProfile {
44
44
  badgeText?: string;
45
45
  }
46
46
  declare class DbNavbar extends HTMLElement {
47
+ private unsubscribeLocale?;
48
+ private autoNavLabel?;
47
49
  private static nextId;
48
50
  private readonly mobileMenuId;
49
51
  private mobileOpen;
@@ -56,6 +58,7 @@ declare class DbNavbar extends HTMLElement {
56
58
  static get observedAttributes(): string[];
57
59
  connectedCallback(): void;
58
60
  disconnectedCallback(): void;
61
+ private syncLocale;
59
62
  attributeChangedCallback(): void;
60
63
  get items(): DbNavbarItem[];
61
64
  set items(value: DbNavbarItem[] | string);