@designbasekorea/ui-wc 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE-WORLD-MAP.md +10 -0
- package/README.md +58 -0
- package/dist/esm/components/db-achievement-list.d.ts +2 -0
- package/dist/esm/components/db-achievement-list.js +1 -1
- package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
- package/dist/esm/components/db-activity-heatmap.js +1 -1
- package/dist/esm/components/db-ad-banner.d.ts +2 -0
- package/dist/esm/components/db-ad-banner.js +1 -1
- package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
- package/dist/esm/components/db-ai-chat-list.js +1 -1
- package/dist/esm/components/db-ai-chat.d.ts +2 -0
- package/dist/esm/components/db-ai-chat.js +1 -1
- package/dist/esm/components/db-ai-file-tree.js +1 -1
- package/dist/esm/components/db-alert.d.ts +1 -0
- package/dist/esm/components/db-alert.js +1 -1
- package/dist/esm/components/db-audio-player.d.ts +2 -0
- package/dist/esm/components/db-audio-player.js +1 -1
- package/dist/esm/components/db-avatar.d.ts +1 -0
- package/dist/esm/components/db-avatar.js +1 -1
- package/dist/esm/components/db-banner.d.ts +2 -0
- package/dist/esm/components/db-banner.js +1 -1
- package/dist/esm/components/db-button.d.ts +7 -1
- package/dist/esm/components/db-button.js +1 -1
- package/dist/esm/components/db-calendar.d.ts +5 -0
- package/dist/esm/components/db-calendar.js +1 -1
- package/dist/esm/components/db-card.d.ts +1 -0
- package/dist/esm/components/db-card.js +1 -1
- package/dist/esm/components/db-chat-composer.d.ts +3 -0
- package/dist/esm/components/db-chat-composer.js +1 -1
- package/dist/esm/components/db-chat-message.d.ts +2 -0
- package/dist/esm/components/db-chat-message.js +1 -1
- package/dist/esm/components/db-chat-room.d.ts +1 -0
- package/dist/esm/components/db-chat-room.js +1 -1
- package/dist/esm/components/db-chat-typing.d.ts +2 -0
- package/dist/esm/components/db-chat-typing.js +1 -1
- package/dist/esm/components/db-chat-widget.d.ts +9 -0
- package/dist/esm/components/db-chat-widget.js +1 -1
- package/dist/esm/components/db-chip.d.ts +2 -0
- package/dist/esm/components/db-chip.js +1 -1
- package/dist/esm/components/db-code-block.d.ts +1 -0
- package/dist/esm/components/db-code-block.js +1 -1
- package/dist/esm/components/db-color-picker.d.ts +4 -0
- package/dist/esm/components/db-color-picker.js +1 -1
- package/dist/esm/components/db-color-swatch.d.ts +3 -0
- package/dist/esm/components/db-color-swatch.js +1 -1
- package/dist/esm/components/db-cookie-banner.d.ts +3 -0
- package/dist/esm/components/db-cookie-banner.js +1 -1
- package/dist/esm/components/db-countdown.d.ts +2 -1
- package/dist/esm/components/db-countdown.js +1 -1
- package/dist/esm/components/db-date-picker.d.ts +3 -0
- package/dist/esm/components/db-date-picker.js +1 -1
- package/dist/esm/components/db-dropdown.d.ts +1 -0
- package/dist/esm/components/db-dropdown.js +1 -1
- package/dist/esm/components/db-dropzone.d.ts +2 -0
- package/dist/esm/components/db-dropzone.js +1 -1
- package/dist/esm/components/db-email-verify.d.ts +1 -0
- package/dist/esm/components/db-email-verify.js +1 -1
- package/dist/esm/components/db-file-uploader.d.ts +2 -0
- package/dist/esm/components/db-file-uploader.js +1 -1
- package/dist/esm/components/db-form.d.ts +2 -0
- package/dist/esm/components/db-form.js +1 -1
- package/dist/esm/components/db-gantt.d.ts +2 -0
- package/dist/esm/components/db-gantt.js +1 -1
- package/dist/esm/components/db-image-list.d.ts +3 -0
- package/dist/esm/components/db-image-list.js +1 -1
- package/dist/esm/components/db-image.d.ts +1 -0
- package/dist/esm/components/db-image.js +1 -1
- package/dist/esm/components/db-input-group.d.ts +30 -0
- package/dist/esm/components/db-input-group.js +1 -0
- package/dist/esm/components/db-input.d.ts +1 -0
- package/dist/esm/components/db-input.js +1 -1
- package/dist/esm/components/db-kanban.d.ts +3 -0
- package/dist/esm/components/db-kanban.js +1 -1
- package/dist/esm/components/db-lightbox.d.ts +2 -0
- package/dist/esm/components/db-lightbox.js +1 -1
- package/dist/esm/components/db-list.d.ts +2 -0
- package/dist/esm/components/db-list.js +1 -1
- package/dist/esm/components/db-markdown-editor.d.ts +2 -0
- package/dist/esm/components/db-markdown-editor.js +1 -1
- package/dist/esm/components/db-menu-item.js +1 -1
- package/dist/esm/components/db-navbar.d.ts +3 -0
- package/dist/esm/components/db-navbar.js +1 -1
- package/dist/esm/components/db-node.d.ts +1 -0
- package/dist/esm/components/db-node.js +1 -1
- package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
- package/dist/esm/components/db-onboarding-modal.js +1 -1
- package/dist/esm/components/db-otp-input.d.ts +4 -1
- package/dist/esm/components/db-otp-input.js +1 -1
- package/dist/esm/components/db-page-header.js +1 -1
- package/dist/esm/components/db-popover.d.ts +1 -0
- package/dist/esm/components/db-popover.js +1 -1
- package/dist/esm/components/db-progress-step.d.ts +2 -0
- package/dist/esm/components/db-progress-step.js +1 -1
- package/dist/esm/components/db-range-slider.d.ts +1 -0
- package/dist/esm/components/db-range-slider.js +1 -1
- package/dist/esm/components/db-rating.d.ts +1 -0
- package/dist/esm/components/db-rating.js +1 -1
- package/dist/esm/components/db-search-bar.d.ts +2 -0
- package/dist/esm/components/db-search-bar.js +1 -1
- package/dist/esm/components/db-section-logo-cloud.js +1 -1
- package/dist/esm/components/db-share.d.ts +5 -0
- package/dist/esm/components/db-share.js +1 -1
- package/dist/esm/components/db-sidebar.d.ts +3 -0
- package/dist/esm/components/db-sidebar.js +1 -1
- package/dist/esm/components/db-signature.d.ts +2 -0
- package/dist/esm/components/db-signature.js +1 -1
- package/dist/esm/components/db-spinner.d.ts +2 -0
- package/dist/esm/components/db-spinner.js +1 -1
- package/dist/esm/components/db-stepper.d.ts +2 -0
- package/dist/esm/components/db-stepper.js +1 -1
- package/dist/esm/components/db-table.d.ts +2 -0
- package/dist/esm/components/db-table.js +1 -1
- package/dist/esm/components/db-tabs.d.ts +1 -0
- package/dist/esm/components/db-tabs.js +1 -1
- package/dist/esm/components/db-ticket.js +1 -1
- package/dist/esm/components/db-time-picker.d.ts +2 -0
- package/dist/esm/components/db-time-picker.js +1 -1
- package/dist/esm/components/db-timeline.d.ts +4 -0
- package/dist/esm/components/db-timeline.js +1 -1
- package/dist/esm/components/db-toast.d.ts +2 -0
- package/dist/esm/components/db-toast.js +1 -1
- package/dist/esm/components/db-tool-layout.d.ts +92 -0
- package/dist/esm/components/db-tool-layout.js +1 -0
- package/dist/esm/components/db-tool-panel.d.ts +50 -0
- package/dist/esm/components/db-tool-panel.js +1 -0
- package/dist/esm/components/db-top-banner.d.ts +2 -0
- package/dist/esm/components/db-top-banner.js +1 -1
- package/dist/esm/components/db-video-player.d.ts +3 -0
- package/dist/esm/components/db-video-player.js +1 -1
- package/dist/esm/components/db-world-map.d.ts +60 -0
- package/dist/esm/components/db-world-map.js +1 -0
- package/dist/esm/components/db-youtube-player.d.ts +2 -0
- package/dist/esm/components/db-youtube-player.js +1 -1
- package/dist/esm/components/db-zoom-control.d.ts +52 -0
- package/dist/esm/components/db-zoom-control.js +1 -0
- package/dist/esm/components/input-validation.js +1 -1
- package/dist/esm/components/paper-card.d.ts +2 -0
- package/dist/esm/components/paper-card.js +1 -1
- package/dist/esm/core/i18n-copy.js +1 -1
- package/dist/esm/core/i18n-en.js +1 -1
- package/dist/esm/core/i18n.d.ts +31 -1
- package/dist/esm/core/i18n.js +1 -1
- package/dist/esm/helpers/world-countries.js +1 -0
- package/dist/esm/helpers/world-land.js +1 -0
- package/dist/esm/index.d.ts +6 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +442 -6
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +837 -71
- package/dist/react/index.esm.js +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as e}from"./db-icons.js";import{dbUid as t}from"../core/uid.js";import{
|
|
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(``)}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(``)}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
|
|
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);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setHostClasses as e}from"../core/host-class.js";import{dbText as t}from"../core/i18n.js";import{createDbIcon as a}from"./db-icons.js";import{sanitizeHref as n}from"../core/safe-url.js";import{NAVBAR_SIZES as s,NAVBAR_VARIANTS as i,NAVBAR_POSITIONS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function resolveIcon(e){if(e)return e}class DbNavbar extends HTMLElement{constructor(){super(...arguments),this.mobileMenuId="db-navbar-menu-"+ ++DbNavbar.nextId,this.mobileOpen=!1,this.escapeMenu=e=>{"Escape"===e.key&&this.mobileOpen&&(e.preventDefault(),this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())},this.userMenuOpen=!1,this.expandedMobile={},this.outsideHandler=null}static get observedAttributes(){return["logo-src","logo-alt","items","user-menu-items","user-profile","size","variant","position","is-authenticated","show-search","search-placeholder","full-width","shadow"]}connectedCallback(){this.render(),this.bindOutsideClick(),this.addEventListener("keydown",this.escapeMenu),this.containerObserver=new ResizeObserver(([e])=>{e.contentRect.width>=1024&&this.mobileOpen&&(this.mobileOpen=!1,this.render())}),this.containerObserver.observe(this),this.slotObserver=new MutationObserver(()=>{Array.from(this.children).some(e=>["brand","actions"].includes(e.getAttribute("slot")||""))&&this.render()}),this.slotObserver.observe(this,{childList:!0})}disconnectedCallback(){this.unbindOutsideClick(),this.slotObserver?.disconnect(),this.containerObserver?.disconnect(),this.removeEventListener("keydown",this.escapeMenu)}attributeChangedCallback(){this.isConnected&&this.render()}get items(){return this.parseItems("items")}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseItems("user-menu-items")}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}parseItems(e="items"){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}iconSize(e){return"s"===e?16:"l"===e?24:20}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{this.contains(e.target)||(this.userMenuOpen=!1,this.updateUserMenuVisibility(),this.mobileOpen&&(this.mobileOpen=!1,this.render()))},document.addEventListener("mousedown",this.outsideHandler))}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}dispatchItemClick(e,t){this.dispatchEvent(new CustomEvent("user"===t?"db-user-menu-item-click":"db-item-click",{bubbles:!0,composed:!0,detail:{item:e,source:t}}))}syncHostClasses(){const t=this.getAttribute("size")||"m",a=this.getAttribute("variant")||"default",n=this.getAttribute("position")||"static";e(this,["designbase-wc-navbar",`designbase-wc-navbar--${s.includes(t)?t:"m"}`,`designbase-wc-navbar--${i.includes(a)?a:"default"}`,`designbase-wc-navbar--${r.includes(n)?n:"static"}`,this.hasAttribute("full-width")&&"designbase-wc-navbar--full-width",this.hasAttribute("shadow")&&"designbase-wc-navbar--shadow",this.mobileOpen&&"designbase-wc-navbar--mobile-open"])}isMegaMenu(e){return Boolean(e.megaMenu&&e.columns?.length)}createNavToggleButton(e,t){const n=document.createElement("button");n.type="button",n.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),n.disabled=Boolean(e.disabled);const s=resolveIcon(e.icon);s&&n.append(a(s,t)),n.append(document.createTextNode(e.label));const i=a("chevron-down",12);return i.classList.add("designbase-wc-navbar__chevron"),n.append(i),n}createMegaLink(e,t){const s=document.createElement("a");s.href=n(e.href,"#"),s.className=["designbase-wc-navbar__mega-link",e.active&&"designbase-wc-navbar__mega-link--active",e.disabled&&"designbase-wc-navbar__mega-link--disabled"].filter(Boolean).join(" ");const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-link-icon",e.append(a(i,t)),s.append(e)}const r=document.createElement("span");r.className="designbase-wc-navbar__mega-link-body";const c=document.createElement("span");if(c.className="designbase-wc-navbar__mega-link-label",c.textContent=e.label,r.append(c),e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-link-desc",t.textContent=e.description,r.append(t)}return s.append(r),s.addEventListener("click",t=>{t.preventDefault(),e.disabled||this.dispatchItemClick(e,"nav")}),s}createMegaMenu(e,t){const a=document.createElement("li");a.className="designbase-wc-navbar__nav-item designbase-wc-navbar__nav-item--mega";const n=this.createNavToggleButton(e,t),s=document.createElement("div");s.className="designbase-wc-navbar__mega";const i=document.createElement("div");i.className="designbase-wc-navbar__mega-inner";const r=document.createElement("div");return r.className="designbase-wc-navbar__mega-columns",e.columns.forEach(e=>{const a=document.createElement("div");if(a.className="designbase-wc-navbar__mega-column",e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-column-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-navbar__mega-list",e.items.forEach(e=>{const a=document.createElement("li");a.append(this.createMegaLink(e,t)),n.append(a)}),a.append(n),r.append(a)}),i.append(r),e.featured&&i.append(this.createMegaFeatured(e.featured,t)),s.append(i),a.append(n,s),a}createMegaFeatured(e,t){const s=document.createElement("a");s.href=n(e.href,"#"),s.className="designbase-wc-navbar__mega-featured",e.image&&(s.style.setProperty("--db-navbar-mega-featured-image",`url("${e.image}")`),s.classList.add("designbase-wc-navbar__mega-featured--image"));const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-featured-icon",e.append(a(i,t+4)),s.append(e)}if(e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-title",t.textContent=e.title,s.append(t)}if(e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-desc",t.textContent=e.description,s.append(t)}if(e.ctaLabel){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-cta",t.append(document.createTextNode(e.ctaLabel)),t.append(a("chevron-right",14)),s.append(t)}return s.addEventListener("click",t=>{t.preventDefault(),this.dispatchItemClick({id:`${e.href||"featured"}`,label:e.title||"featured",href:e.href},"nav")}),s}createDesktopNavItem(e,t){if(this.isMegaMenu(e))return this.createMegaMenu(e,t);const s=document.createElement("li");s.className="designbase-wc-navbar__nav-item";if(Boolean(e.children?.length)){const i=document.createElement("div");i.className="designbase-wc-navbar__dropdown";const r=document.createElement("button");r.type="button",r.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),r.disabled=Boolean(e.disabled);const c=resolveIcon(e.icon);c&&r.append(a(c,t)),r.append(document.createTextNode(e.label));const d=a("chevron-down",12);d.classList.add("designbase-wc-navbar__chevron"),r.append(d);const l=document.createElement("ul");return l.className="designbase-wc-navbar__dropdown-menu",e.children.forEach(e=>{const s=document.createElement("li"),i=document.createElement("a");i.href=n(e.href,"#"),i.className=["designbase-wc-navbar__dropdown-item",e.active&&"designbase-wc-navbar__dropdown-item--active",e.disabled&&"designbase-wc-navbar__dropdown-item--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);r&&i.append(a(r,t)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),s.append(i),l.append(s)}),i.append(r,l),s.append(i),s}const i=document.createElement("a");i.href=n(e.href,"#"),i.className=["designbase-wc-navbar__nav-link",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);return r&&i.append(a(r,t)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),s.append(i),s}createUserMenuItemElement(e,t,a){const s=document.createElement("db-menu-item");s.setAttribute("label",e.label),s.setAttribute("type","block"),s.setAttribute("menu-style","dropdown"),s.setAttribute("size",t);const i=n(e.href,"");return i&&s.setAttribute("href",i),e.icon&&s.setAttribute("icon",e.icon),e.disabled&&s.setAttribute("disabled",""),s.addEventListener("db-click",()=>{e.disabled||(a(),this.dispatchItemClick(e,"user"))}),s}bindSearchEvents(e){e.addEventListener("db-search",e=>{const t=e.detail,a=t.query??t.value??"";this.dispatchEvent(new CustomEvent("db-search",{bubbles:!0,composed:!0,detail:{query:a,value:a}}))})}applyAvatarProfile(e,t,a){e.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),e.setAttribute("initials",t.name),e.setAttribute("alt",t.name),t.avatar&&e.setAttribute("src",t.avatar),void 0!==t.badge&&e.setAttribute("badge",String(t.badge)),t.badgeVariant&&e.setAttribute("badge-variant",t.badgeVariant),t.badgeType&&e.setAttribute("badge-type",t.badgeType),t.badgeText&&e.setAttribute("badge-text",t.badgeText)}getMobileChildren(e){if(this.isMegaMenu(e)){const t=(e.columns||[]).flatMap(e=>e.items);return e.featured?.href&&t.push({id:`${e.id}-featured`,label:e.featured.title||e.featured.ctaLabel||e.label,href:e.featured.href,icon:e.featured.icon}),t}return e.children||[]}createMobileMenuItem(e,t){const a=this.getMobileChildren(e),s=a.length>0,i=Boolean(this.expandedMobile[e.id]),r=document.createElement("db-menu-item");r.setAttribute("label",e.label),r.setAttribute("type","block"),r.setAttribute("menu-style","accordion"),r.setAttribute("size",t);const c=n(e.href,"");return c&&r.setAttribute("href",c),e.icon&&r.setAttribute("icon",e.icon),e.active&&r.setAttribute("active",""),e.disabled&&r.setAttribute("disabled",""),s&&(r.setAttribute("expandable",""),r.subItems=a.map(e=>({id:e.id,label:e.label,href:e.href,icon:e.icon,active:e.active,disabled:e.disabled})),i&&r.setAttribute("expanded","")),r.addEventListener("db-click",()=>{e.disabled||(s?this.expandedMobile[e.id]=r.hasAttribute("expanded"):(this.mobileOpen=!1,this.dispatchItemClick(e,"mobile"),this.render()))}),r.addEventListener("db-child-click",e=>{const t=e.detail;this.mobileOpen=!1,this.dispatchItemClick(t.child,"mobile"),this.render()}),r}updateUserMenuVisibility(){const e=this.querySelector(".designbase-wc-navbar__user-dropdown-menu");e&&(e.hidden=!this.userMenuOpen)}renderMobileMenu(){const e=this.querySelector(".designbase-wc-navbar__mobile-nav-list");if(!e)return;const t=this.getAttribute("size")||"m",a=this.parseItems();e.replaceChildren(...a.map(e=>this.createMobileMenuItem(e,t)))}render(){this.syncHostClasses(),this.setAttribute("role","navigation"),this.hasAttribute("aria-label")||this.setAttribute("aria-label",t("메인 네비게이션"));const e=this.getAttribute("size")||"m",n=this.iconSize(e),s=this.parseItems(),i=this.parseItems("user-menu-items"),r=this.parseUserProfile(),c=this.hasAttribute("is-authenticated"),d=this.hasAttribute("show-search"),l=this.querySelector('[slot="brand"]'),o=this.querySelector('[slot="actions"]');this.replaceChildren();const b=document.createElement("div");b.className=["designbase-wc-navbar__container",this.hasAttribute("full-width")&&"designbase-wc-navbar__container--full-width"].filter(Boolean).join(" ");const u=document.createElement("div");u.className="designbase-wc-navbar__left";const m=document.createElement("div");m.className="designbase-wc-navbar__brand";const p=document.createElement("div");p.className="designbase-wc-navbar__logo";const h=document.createElement("db-logo"),v=this.getAttribute("logo-src");h.setAttribute("type",v?"custom":"designbase"),v&&h.setAttribute("src",v),h.setAttribute("alt",this.getAttribute("logo-alt")||"홈"),h.setAttribute("size","s"),h.setAttribute("clickable",""),h.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),p.append(h),m.append(l||p),u.append(m);const g=document.createElement("div");g.className="designbase-wc-navbar__right";const _=document.createElement("div");_.className="designbase-wc-navbar__nav designbase-wc-navbar__nav--desktop";const f=document.createElement("ul");if(f.className="designbase-wc-navbar__nav-list",s.forEach(e=>f.append(this.createDesktopNavItem(e,n))),_.append(f),g.append(_),d){const t=document.createElement("div");t.className="designbase-wc-navbar__search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"===e?"s":"l"===e?"l":"m"),a.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(a),t.append(a),g.append(t)}const w=document.createElement("div");if(w.className="designbase-wc-navbar__user-menu",c&&r){const t=document.createElement("div");t.className="designbase-wc-navbar__user-dropdown";const n=document.createElement("button");n.type="button",n.className="designbase-wc-navbar__user-toggle",n.setAttribute("aria-expanded",String(this.userMenuOpen));const s=document.createElement("db-avatar");this.applyAvatarProfile(s,r,e);const c=document.createElement("span");c.className="designbase-wc-navbar__user-name",c.textContent=r.name,n.append(s,c,a("chevron-down",12)),n.addEventListener("click",()=>{this.userMenuOpen=!this.userMenuOpen,n.setAttribute("aria-expanded",String(this.userMenuOpen)),this.updateUserMenuVisibility()});const d=document.createElement("ul");if(d.className="designbase-wc-navbar__user-dropdown-menu",d.hidden=!this.userMenuOpen,r.email){const e=document.createElement("li");e.className="designbase-wc-navbar__user-info";const t=document.createElement("span");t.className="designbase-wc-navbar__user-email",t.textContent=r.email,e.append(t),d.append(e)}i.forEach(t=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(t,e,()=>{this.userMenuOpen=!1,this.updateUserMenuVisibility()})),d.append(a)}),t.append(n,d),w.append(t)}else{const a=document.createElement("db-button");a.setAttribute("variant","primary"),a.setAttribute("size","s"===e?"s":"l"===e?"l":"m"),a.textContent=t("로그인"),a.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),w.append(a)}g.append(o||w);const E=document.createElement("button");E.type="button",E.className="designbase-wc-navbar__mobile-toggle",E.setAttribute("aria-expanded",String(this.mobileOpen)),this.mobileOpen&&E.setAttribute("aria-controls",this.mobileMenuId),E.setAttribute("aria-label",t(this.mobileOpen?"메뉴 닫기":"메뉴 열기"));for(let e=0;e<3;e+=1){const e=document.createElement("span");e.className="designbase-wc-navbar__mobile-toggle-line",E.append(e)}if(E.addEventListener("click",()=>{this.mobileOpen=!this.mobileOpen,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus()}),b.append(u,g,E),this.append(b),this.mobileOpen){const e=document.createElement("div");if(e.className="designbase-wc-navbar__mobile-menu",e.id=this.mobileMenuId,e.addEventListener("keydown",e=>{"Escape"===e.key&&(this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())}),d){const t=document.createElement("div");t.className="designbase-wc-navbar__mobile-search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"),a.setAttribute("full-width",""),a.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(a),t.append(a),e.append(t)}const a=document.createElement("div");a.className="designbase-wc-navbar__mobile-nav-list",e.append(a);const n=document.createElement("div");if(n.className="designbase-wc-navbar__mobile-user",c&&r){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-info";const t=document.createElement("db-avatar");this.applyAvatarProfile(t,r,"m");const a=document.createElement("div"),s=document.createElement("div");if(s.className="designbase-wc-navbar__mobile-user-name",s.textContent=r.name,a.append(s),r.email){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-email",e.textContent=r.email,a.append(e)}if(e.append(t,a),n.append(e),i.length){const e=document.createElement("ul");e.className="designbase-wc-navbar__mobile-user-menu",i.forEach(t=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(t,"m",()=>{this.mobileOpen=!1,this.render()})),e.append(a)}),n.append(e)}}else{const e=document.createElement("db-button");e.setAttribute("variant","primary"),e.setAttribute("size","m"),e.setAttribute("full-width",""),e.textContent=t("로그인"),e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),n.append(e)}o||e.append(n),this.append(e),this.renderMobileMenu()}}}DbNavbar.nextId=0,customElements.get("db-navbar")||customElements.define("db-navbar",DbNavbar);export{DbNavbar};
|
|
1
|
+
import{setHostClasses as e}from"../core/host-class.js";import{subscribeDbLocale as t,dbText as a}from"../core/i18n.js";import{createDbIcon as n}from"./db-icons.js";import{sanitizeHref as s}from"../core/safe-url.js";import{NAVBAR_SIZES as i,NAVBAR_VARIANTS as r,NAVBAR_POSITIONS as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function resolveIcon(e){if(e)return e}class DbNavbar extends HTMLElement{constructor(){super(...arguments),this.mobileMenuId="db-navbar-menu-"+ ++DbNavbar.nextId,this.mobileOpen=!1,this.escapeMenu=e=>{"Escape"===e.key&&this.mobileOpen&&(e.preventDefault(),this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())},this.userMenuOpen=!1,this.expandedMobile={},this.outsideHandler=null}static get observedAttributes(){return["logo-src","logo-alt","items","user-menu-items","user-profile","size","variant","position","is-authenticated","show-search","search-placeholder","full-width","shadow"]}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.syncLocale()),this.render(),this.bindOutsideClick(),this.addEventListener("keydown",this.escapeMenu),this.containerObserver=new ResizeObserver(([e])=>{e.contentRect.width>=1024&&this.mobileOpen&&(this.mobileOpen=!1,this.render())}),this.containerObserver.observe(this),this.slotObserver=new MutationObserver(()=>{Array.from(this.children).some(e=>["brand","actions"].includes(e.getAttribute("slot")||""))&&this.render()}),this.slotObserver.observe(this,{childList:!0})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.unbindOutsideClick(),this.slotObserver?.disconnect(),this.containerObserver?.disconnect(),this.removeEventListener("keydown",this.escapeMenu)}syncLocale(){const e=this.getAttribute("aria-label");e&&e!==this.autoNavLabel||(this.autoNavLabel=a("메인 네비게이션"),this.setAttribute("aria-label",this.autoNavLabel));const t=this.querySelector(".designbase-wc-navbar__logo db-logo");t&&t.setAttribute("alt",this.getAttribute("logo-alt")||a("홈")),this.querySelectorAll("[data-navbar-login]").forEach(e=>{e.textContent=a("로그인")}),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.setAttribute("aria-label",a(this.mobileOpen?"메뉴 닫기":"메뉴 열기"))}attributeChangedCallback(){this.isConnected&&this.render()}get items(){return this.parseItems("items")}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseItems("user-menu-items")}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}parseItems(e="items"){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}iconSize(e){return"s"===e?16:"l"===e?24:20}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{this.contains(e.target)||(this.userMenuOpen=!1,this.updateUserMenuVisibility(),this.mobileOpen&&(this.mobileOpen=!1,this.render()))},document.addEventListener("mousedown",this.outsideHandler))}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}dispatchItemClick(e,t){this.dispatchEvent(new CustomEvent("user"===t?"db-user-menu-item-click":"db-item-click",{bubbles:!0,composed:!0,detail:{item:e,source:t}}))}syncHostClasses(){const t=this.getAttribute("size")||"m",a=this.getAttribute("variant")||"default",n=this.getAttribute("position")||"static";e(this,["designbase-wc-navbar",`designbase-wc-navbar--${i.includes(t)?t:"m"}`,`designbase-wc-navbar--${r.includes(a)?a:"default"}`,`designbase-wc-navbar--${c.includes(n)?n:"static"}`,this.hasAttribute("full-width")&&"designbase-wc-navbar--full-width",this.hasAttribute("shadow")&&"designbase-wc-navbar--shadow",this.mobileOpen&&"designbase-wc-navbar--mobile-open"])}isMegaMenu(e){return Boolean(e.megaMenu&&e.columns?.length)}createNavToggleButton(e,t){const a=document.createElement("button");a.type="button",a.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),a.disabled=Boolean(e.disabled);const s=resolveIcon(e.icon);s&&a.append(n(s,t)),a.append(document.createTextNode(e.label));const i=n("chevron-down",12);return i.classList.add("designbase-wc-navbar__chevron"),a.append(i),a}createMegaLink(e,t){const a=document.createElement("a");a.href=s(e.href,"#"),a.className=["designbase-wc-navbar__mega-link",e.active&&"designbase-wc-navbar__mega-link--active",e.disabled&&"designbase-wc-navbar__mega-link--disabled"].filter(Boolean).join(" ");const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-link-icon",e.append(n(i,t)),a.append(e)}const r=document.createElement("span");r.className="designbase-wc-navbar__mega-link-body";const c=document.createElement("span");if(c.className="designbase-wc-navbar__mega-link-label",c.textContent=e.label,r.append(c),e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-link-desc",t.textContent=e.description,r.append(t)}return a.append(r),a.addEventListener("click",t=>{t.preventDefault(),e.disabled||this.dispatchItemClick(e,"nav")}),a}createMegaMenu(e,t){const a=document.createElement("li");a.className="designbase-wc-navbar__nav-item designbase-wc-navbar__nav-item--mega";const n=this.createNavToggleButton(e,t),s=document.createElement("div");s.className="designbase-wc-navbar__mega";const i=document.createElement("div");i.className="designbase-wc-navbar__mega-inner";const r=document.createElement("div");return r.className="designbase-wc-navbar__mega-columns",e.columns.forEach(e=>{const a=document.createElement("div");if(a.className="designbase-wc-navbar__mega-column",e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-column-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-navbar__mega-list",e.items.forEach(e=>{const a=document.createElement("li");a.append(this.createMegaLink(e,t)),n.append(a)}),a.append(n),r.append(a)}),i.append(r),e.featured&&i.append(this.createMegaFeatured(e.featured,t)),s.append(i),a.append(n,s),a}createMegaFeatured(e,t){const a=document.createElement("a");a.href=s(e.href,"#"),a.className="designbase-wc-navbar__mega-featured",e.image&&(a.style.setProperty("--db-navbar-mega-featured-image",`url("${e.image}")`),a.classList.add("designbase-wc-navbar__mega-featured--image"));const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-featured-icon",e.append(n(i,t+4)),a.append(e)}if(e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-title",t.textContent=e.title,a.append(t)}if(e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-desc",t.textContent=e.description,a.append(t)}if(e.ctaLabel){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-cta",t.append(document.createTextNode(e.ctaLabel)),t.append(n("chevron-right",14)),a.append(t)}return a.addEventListener("click",t=>{t.preventDefault(),this.dispatchItemClick({id:`${e.href||"featured"}`,label:e.title||"featured",href:e.href},"nav")}),a}createDesktopNavItem(e,t){if(this.isMegaMenu(e))return this.createMegaMenu(e,t);const a=document.createElement("li");a.className="designbase-wc-navbar__nav-item";if(Boolean(e.children?.length)){const i=document.createElement("div");i.className="designbase-wc-navbar__dropdown";const r=document.createElement("button");r.type="button",r.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),r.disabled=Boolean(e.disabled);const c=resolveIcon(e.icon);c&&r.append(n(c,t)),r.append(document.createTextNode(e.label));const d=n("chevron-down",12);d.classList.add("designbase-wc-navbar__chevron"),r.append(d);const o=document.createElement("ul");return o.className="designbase-wc-navbar__dropdown-menu",e.children.forEach(e=>{const a=document.createElement("li"),i=document.createElement("a");i.href=s(e.href,"#"),i.className=["designbase-wc-navbar__dropdown-item",e.active&&"designbase-wc-navbar__dropdown-item--active",e.disabled&&"designbase-wc-navbar__dropdown-item--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);r&&i.append(n(r,t)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),a.append(i),o.append(a)}),i.append(r,o),a.append(i),a}const i=document.createElement("a");i.href=s(e.href,"#"),i.className=["designbase-wc-navbar__nav-link",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);return r&&i.append(n(r,t)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),a.append(i),a}createUserMenuItemElement(e,t,a){const n=document.createElement("db-menu-item");n.setAttribute("label",e.label),n.setAttribute("type","block"),n.setAttribute("menu-style","dropdown"),n.setAttribute("size",t);const i=s(e.href,"");return i&&n.setAttribute("href",i),e.icon&&n.setAttribute("icon",e.icon),e.disabled&&n.setAttribute("disabled",""),n.addEventListener("db-navigate",t=>{e.disabled||(t.preventDefault(),this.mobileOpen=!1,this.dispatchItemClick(e,"mobile"),this.render())}),n.addEventListener("db-click",()=>{e.disabled||(a(),this.dispatchItemClick(e,"user"))}),n}bindSearchEvents(e){e.addEventListener("db-search",e=>{const t=e.detail,a=t.query??t.value??"";this.dispatchEvent(new CustomEvent("db-search",{bubbles:!0,composed:!0,detail:{query:a,value:a}}))})}applyAvatarProfile(e,t,a){e.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),e.setAttribute("initials",t.name),e.setAttribute("alt",t.name),t.avatar&&e.setAttribute("src",t.avatar),void 0!==t.badge&&e.setAttribute("badge",String(t.badge)),t.badgeVariant&&e.setAttribute("badge-variant",t.badgeVariant),t.badgeType&&e.setAttribute("badge-type",t.badgeType),t.badgeText&&e.setAttribute("badge-text",t.badgeText)}getMobileChildren(e){if(this.isMegaMenu(e)){const t=(e.columns||[]).flatMap(e=>e.items);return e.featured?.href&&t.push({id:`${e.id}-featured`,label:e.featured.title||e.featured.ctaLabel||e.label,href:e.featured.href,icon:e.featured.icon}),t}return e.children||[]}createMobileMenuItem(e,t){const a=this.getMobileChildren(e),n=a.length>0,i=Boolean(this.expandedMobile[e.id]),r=document.createElement("db-menu-item");r.setAttribute("label",e.label),r.setAttribute("type","block"),r.setAttribute("menu-style","accordion"),r.setAttribute("size",t);const c=s(e.href,"");return c&&r.setAttribute("href",c),e.icon&&r.setAttribute("icon",e.icon),e.active&&r.setAttribute("active",""),e.disabled&&r.setAttribute("disabled",""),n&&(r.setAttribute("expandable",""),c&&r.setAttribute("split-expand",""),r.subItems=a.map(e=>({id:e.id,label:e.label,href:e.href,icon:e.icon,active:e.active,disabled:e.disabled})),i&&r.setAttribute("expanded","")),r.addEventListener("db-click",()=>{if(!e.disabled){if(n){const t=r.hasAttribute("expanded");this.expandedMobile[e.id]=t;const a=r.querySelector(":scope > .designbase-wc-menu-item__children--accordion");if(a&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches){a.getAnimations().forEach(e=>e.cancel());const e=a.scrollHeight+"px";a.animate(t?[{maxHeight:"0px",opacity:0},{maxHeight:e,opacity:1}]:[{maxHeight:e,opacity:1},{maxHeight:"0px",opacity:0}],{duration:240,easing:"cubic-bezier(.22, 1, .36, 1)"})}return}this.mobileOpen=!1,this.dispatchItemClick(e,"mobile"),this.render()}}),r.addEventListener("db-child-click",e=>{const t=e.detail;this.mobileOpen=!1,this.dispatchItemClick(t.child,"mobile"),this.render()}),r}updateUserMenuVisibility(){const e=this.querySelector(".designbase-wc-navbar__user-dropdown-menu");e&&(e.hidden=!this.userMenuOpen)}renderMobileMenu(){const e=this.querySelector(".designbase-wc-navbar__mobile-nav-list");if(!e)return;const t=this.getAttribute("size")||"m",a=this.parseItems();e.replaceChildren(...a.map(e=>this.createMobileMenuItem(e,t)))}render(){const e=this.querySelector(".designbase-wc-navbar__mobile-menu:not([data-exiting])"),t="true"===this.querySelector(".designbase-wc-navbar__mobile-toggle")?.getAttribute("aria-expanded")!==this.mobileOpen&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches,s=t?Array.from(this.querySelectorAll(".designbase-wc-navbar__mobile-toggle-line")).map(e=>({transform:getComputedStyle(e).transform,opacity:getComputedStyle(e).opacity})):[];this.syncHostClasses(),this.setAttribute("role","navigation"),this.syncLocale();const i=this.getAttribute("size")||"m",r=this.iconSize(i),c=this.parseItems(),d=this.parseItems("user-menu-items"),o=this.parseUserProfile(),l=this.hasAttribute("is-authenticated"),b=this.hasAttribute("show-search"),u=this.querySelector('[slot="brand"]'),m=this.querySelector('[slot="actions"]'),p=this.querySelector('[slot="mobile-footer"]');this.replaceChildren();const h=document.createElement("div");h.className=["designbase-wc-navbar__container",this.hasAttribute("full-width")&&"designbase-wc-navbar__container--full-width"].filter(Boolean).join(" ");const v=document.createElement("div");v.className="designbase-wc-navbar__left";const g=document.createElement("div");g.className="designbase-wc-navbar__brand";const _=document.createElement("div");_.className="designbase-wc-navbar__logo";const f=document.createElement("db-logo"),w=this.getAttribute("logo-src");f.setAttribute("type",w?"custom":"designbase"),w&&f.setAttribute("src",w),f.setAttribute("alt",this.getAttribute("logo-alt")||a("홈")),f.setAttribute("size","s"),f.setAttribute("clickable",""),f.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),_.append(f),g.append(u||_),v.append(g);const E=document.createElement("div");E.className="designbase-wc-navbar__right";const A=document.createElement("div");A.className="designbase-wc-navbar__nav designbase-wc-navbar__nav--desktop";const y=document.createElement("ul");if(y.className="designbase-wc-navbar__nav-list",c.forEach(e=>y.append(this.createDesktopNavItem(e,r))),A.append(y),E.append(A),b){const e=document.createElement("div");e.className="designbase-wc-navbar__search";const t=document.createElement("db-search-bar");t.setAttribute("variant","outlined"),t.setAttribute("size","s"===i?"s":"l"===i?"l":"m"),this.getAttribute("search-placeholder")&&t.setAttribute("placeholder",this.getAttribute("search-placeholder")),this.bindSearchEvents(t),e.append(t),E.append(e)}const N=document.createElement("div");if(N.className="designbase-wc-navbar__user-menu",l&&o){const e=document.createElement("div");e.className="designbase-wc-navbar__user-dropdown";const t=document.createElement("button");t.type="button",t.className="designbase-wc-navbar__user-toggle",t.setAttribute("aria-expanded",String(this.userMenuOpen));const a=document.createElement("db-avatar");this.applyAvatarProfile(a,o,i);const s=document.createElement("span");s.className="designbase-wc-navbar__user-name",s.textContent=o.name,t.append(a,s,n("chevron-down",12)),t.addEventListener("click",()=>{this.userMenuOpen=!this.userMenuOpen,t.setAttribute("aria-expanded",String(this.userMenuOpen)),this.updateUserMenuVisibility()});const r=document.createElement("ul");if(r.className="designbase-wc-navbar__user-dropdown-menu",r.hidden=!this.userMenuOpen,o.email){const e=document.createElement("li");e.className="designbase-wc-navbar__user-info";const t=document.createElement("span");t.className="designbase-wc-navbar__user-email",t.textContent=o.email,e.append(t),r.append(e)}d.forEach(e=>{const t=document.createElement("li");t.append(this.createUserMenuItemElement(e,i,()=>{this.userMenuOpen=!1,this.updateUserMenuVisibility()})),r.append(t)}),e.append(t,r),N.append(e)}else{const e=document.createElement("db-button");e.dataset.navbarLogin="",e.setAttribute("variant","primary"),e.setAttribute("size","s"===i?"s":"l"===i?"l":"m"),e.textContent=a("로그인"),e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),N.append(e)}E.append(m||N);const k=document.createElement("button");k.type="button",k.className="designbase-wc-navbar__mobile-toggle",k.setAttribute("aria-expanded",String(this.mobileOpen)),this.mobileOpen&&k.setAttribute("aria-controls",this.mobileMenuId),k.setAttribute("aria-label",a(this.mobileOpen?"메뉴 닫기":"메뉴 열기"));for(let e=0;e<3;e+=1){const e=document.createElement("span");e.className="designbase-wc-navbar__mobile-toggle-line",k.append(e)}if(k.addEventListener("click",()=>{this.mobileOpen=!this.mobileOpen,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus()}),h.append(v,E,k),this.append(h),this.mobileOpen){const e=document.createElement("div");if(e.className="designbase-wc-navbar__mobile-menu",e.id=this.mobileMenuId,e.addEventListener("keydown",e=>{"Escape"===e.key&&(this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())}),b){const t=document.createElement("div");t.className="designbase-wc-navbar__mobile-search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"),a.setAttribute("full-width",""),this.getAttribute("search-placeholder")&&a.setAttribute("placeholder",this.getAttribute("search-placeholder")),this.bindSearchEvents(a),t.append(a),e.append(t)}const n=document.createElement("div");n.className="designbase-wc-navbar__mobile-nav-list",e.append(n);const s=document.createElement("div");if(s.className="designbase-wc-navbar__mobile-user",l&&o){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-info";const t=document.createElement("db-avatar");this.applyAvatarProfile(t,o,"m");const a=document.createElement("div"),n=document.createElement("div");if(n.className="designbase-wc-navbar__mobile-user-name",n.textContent=o.name,a.append(n),o.email){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-email",e.textContent=o.email,a.append(e)}if(e.append(t,a),s.append(e),d.length){const e=document.createElement("ul");e.className="designbase-wc-navbar__mobile-user-menu",d.forEach(t=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(t,"m",()=>{this.mobileOpen=!1,this.render()})),e.append(a)}),s.append(e)}}else{const e=document.createElement("db-button");e.dataset.navbarLogin="",e.setAttribute("variant","primary"),e.setAttribute("size","m"),e.setAttribute("full-width",""),e.textContent=a("로그인"),e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),s.append(e)}p?(p.hidden=!1,e.append(p),e.addEventListener("click",e=>{e.target instanceof Element&&e.target.closest('[slot="mobile-footer"] a, [slot="mobile-footer"] db-button')&&queueMicrotask(()=>{this.mobileOpen&&(this.mobileOpen=!1,this.render())})})):m||e.append(s),this.append(e),this.renderMobileMenu(),t&&(e.animate([{opacity:0,transform:"translateY(-10px)",clipPath:"inset(0 0 100% 0)"},{opacity:1,transform:"translateY(0)",clipPath:"inset(0)"}],{duration:280,easing:"cubic-bezier(.22, 1, .36, 1)"}),n.animate([{opacity:0,transform:"translateY(-6px)"},{opacity:1,transform:"translateY(0)"}],{duration:240,delay:50,fill:"backwards",easing:"ease-out"}))}else if(t&&e){if(p){const t=p.cloneNode(!0);t.removeAttribute("slot"),e.append(t)}e.dataset.exiting="",e.removeAttribute("id"),e.inert=!0,e.setAttribute("aria-hidden","true"),e.style.pointerEvents="none",this.append(e);e.animate([{opacity:1,transform:"translateY(0)",clipPath:"inset(0)"},{opacity:0,transform:"translateY(-8px)",clipPath:"inset(0 0 100% 0)"}],{duration:180,easing:"ease-in",fill:"forwards"}).onfinish=()=>e.remove()}!this.mobileOpen&&p&&(p.hidden=!0,this.append(p)),t&&k.querySelectorAll(".designbase-wc-navbar__mobile-toggle-line").forEach((e,t)=>{s[t]&&e.animate([s[t],{transform:getComputedStyle(e).transform,opacity:getComputedStyle(e).opacity}],{duration:240,easing:"cubic-bezier(.22, 1, .36, 1)"})})}}DbNavbar.nextId=0,customElements.get("db-navbar")||customElements.define("db-navbar",DbNavbar);export{DbNavbar};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbFormat as t,dbText as e}from"../core/i18n.js";import{DbElement as i}from"../core/base-element.js";import{createDbIcon as s}from"./db-icons.js";import"./db-badge.js";import{nodeStyle as n}from"./node-style.js";import{NODE_VARIANTS as o,NODE_STATUSES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a=new Set(["any","text","image","number","boolean"]),typeLabels=()=>({any:e("일반"),text:e("텍스트"),image:e("이미지"),number:e("숫자"),boolean:e("조건")}),d={idle:"대기",running:"실행 중",success:"완료",error:"오류"};class DbNode extends i{constructor(){super(...arguments),this.root=this.attachShadow({mode:"open"}),this.inputPorts=[],this.outputPorts=[],this.portsDirty=!0,this.drag=null,this.portDrag=null,this.suppressPortClick=!1}static get observedAttributes(){return["node-id","heading","description","icon","variant","status","selected","collapsed","disabled","movable","runnable","collapsible","inputs","outputs","detail","deletable"]}get inputs(){return this.inputPorts.map(t=>({...t}))}set inputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.inputPorts)&&(this.inputPorts=e,this.portsDirty=!0,this.sync())}get outputs(){return this.outputPorts.map(t=>({...t}))}set outputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.outputPorts)&&(this.outputPorts=e,this.portsDirty=!0,this.sync())}getPortElement(t,e){const i="input"===e?this.inputList:this.outputList;return[...i?.querySelectorAll("button")||[]].find(e=>e.dataset.portId===t)||null}connectedCallback(){this.root.childElementCount||this.build(),this.upgradeProperties(["inputs","outputs"]);for(const t of["inputs","outputs"])this.hasAttribute(t)&&this.readPorts(t);this.sync()}disconnectedCallback(){this.finishDrag("end"),this.cancelPortDrag(),super.disconnectedCallback()}attributeChangedCallback(t){"inputs"!==t&&"outputs"!==t||this.readPorts(t),"disabled"===t&&this.hasAttribute("disabled")&&(this.finishDrag("end"),this.cancelPortDrag()),this.sync()}normalizePorts(t){if(!Array.isArray(t))return[];const e=new Set;return t.filter(t=>t&&"string"==typeof t.id&&t.id&&"string"==typeof t.label&&!e.has(t.id)&&e.add(t.id)).map(t=>({id:t.id,label:t.label,type:a.has(t.type)?t.type:"any",connected:!!t.connected,disabled:!!t.disabled}))}readPorts(t){let e=[];try{e=JSON.parse(this.getAttribute(t)||"[]")}catch{}"inputs"===t?this.inputPorts=this.normalizePorts(e):this.outputPorts=this.normalizePorts(e),this.portsDirty=!0}nodeId(){return this.getAttribute("node-id")||this.id}el(t,e){const i=document.createElement(t);return i.className=e,i}action(t,e){const i=this.el("button","action");return i.type="button",i.setAttribute("aria-label",t),i.title=t,i.append(s(e,16)),i}build(){const t=document.createElement("style");t.textContent=n;const e=this.el("article","frame");e.part.add("frame");const i=this.el("header","header");i.part.add("header"),this.headingButton=this.el("button","heading"),this.headingButton.type="button",this.iconBox=this.el("span","icon"),this.iconBox.setAttribute("aria-hidden","true"),this.titleEl=this.el("span","title"),this.headingButton.append(this.iconBox,this.titleEl),this.statusEl=this.el("span","status"),this.statusEl.setAttribute("role","status"),this.statusBadge=document.createElement("db-badge"),this.statusBadge.setAttribute("size","s"),this.statusBadge.setAttribute("type","outlined"),this.statusEl.append(this.statusBadge);const s=this.el("div","actions"),o=document.createElement("slot");o.name="actions",this.runButton=this.action("노드 실행","play-outline"),this.runButton.classList.add("action--run"),this.collapseButton=this.action("노드 접기","chevron-up"),this.deleteButton=this.action("노드 삭제","close"),this.deleteButton.addEventListener("click",()=>this.dbEmit("delete",{nodeId:this.nodeId()},{cancelable:!0})),s.append(o,this.runButton,this.collapseButton,this.deleteButton),i.append(this.headingButton,this.statusEl,s),this.descriptionEl=this.el("p","description"),this.inputList=this.el("div","ports ports--input"),this.inputList.part.add("inputs"),this.outputList=this.el("div","ports ports--output"),this.outputList.part.add("outputs"),this.body=this.el("div","body"),this.body.part.add("body"),this.body.append(document.createElement("slot")),this.footer=this.el("footer","footer");const r=document.createElement("slot");r.name="footer",this.footer.append(r);this.root.addEventListener("slotchange",()=>{this.body.hidden=this.hasAttribute("collapsed")||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=this.hasAttribute("collapsed")||!r.assignedNodes({flatten:!0}).length}),e.append(i,this.descriptionEl,this.inputList,this.body,this.outputList,this.footer),this.root.append(t,e);const isEditor=t=>t.composedPath().some(t=>t instanceof HTMLElement&&(t.isContentEditable||t.matches("input, textarea, db-input, db-textarea, db-markdown-editor")));this.addEventListener("selectstart",t=>{isEditor(t)||t.preventDefault()}),this.addEventListener("dragstart",t=>{isEditor(t)||t.preventDefault()}),this.headingButton.addEventListener("click",()=>{this.hasAttribute("disabled")||this.dbEmit("select",{nodeId:this.nodeId()})}),this.collapseButton.addEventListener("click",()=>{const t=!this.hasAttribute("collapsed");this.toggleAttribute("collapsed",t),this.dbEmit("collapse",{nodeId:this.nodeId(),collapsed:t})}),this.runButton.addEventListener("click",()=>this.dbEmit("run",{nodeId:this.nodeId()},{cancelable:!0})),this.headingButton.addEventListener("pointerdown",t=>{this.hasAttribute("movable")&&!this.hasAttribute("disabled")&&0===t.button&&(this.drag={id:t.pointerId,x:t.clientX,y:t.clientY,lastX:t.clientX,lastY:t.clientY},this.headingButton.setPointerCapture(t.pointerId),this.emitMove("start",0,0))}),this.headingButton.addEventListener("pointermove",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.emitMove("move",t.clientX-this.drag.x,t.clientY-this.drag.y))}),this.headingButton.addEventListener("pointerup",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.finishDrag("end"))}),this.headingButton.addEventListener("pointercancel",()=>this.finishDrag("end")),this.headingButton.addEventListener("lostpointercapture",()=>this.finishDrag("end")),this.headingButton.addEventListener("keydown",t=>{if("Escape"===t.key&&this.drag)return void this.finishDrag("cancel");if(!this.hasAttribute("movable")||this.hasAttribute("disabled"))return;const e={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};if(e[t.key]){t.preventDefault();const[i,s]=e[t.key],n=t.shiftKey?4:16;this.emitMove("keyboard",i*n,s*n)}})}emitMove(t,e,i){this.dbEmit("move",{nodeId:this.nodeId(),deltaX:e,deltaY:i,phase:t})}finishDrag(t){const e=this.drag;e&&(this.drag=null,this.emitMove(t,"cancel"===t?0:e.lastX-e.x,"cancel"===t?0:e.lastY-e.y),this.headingButton.hasPointerCapture(e.id)&&this.headingButton.releasePointerCapture(e.id))}renderPorts(i,s,n){const o=this.root.activeElement,r=o&&i.contains(o)?o.dataset.portId:void 0;this.cancelPortDrag(),i.replaceChildren(),i.hidden=!s.length;for(const o of s){const s=this.el("div","port-row");s.dataset.type=o.type||"any";const r=this.el("button","port");r.type="button",r.part.add("port"),r.dataset.portId=o.id,r.dataset.direction=n,r.disabled=this.hasAttribute("disabled")||!!o.disabled,r.dataset.connected=String(!!o.connected),r.setAttribute("aria-label",t("{0} · {1} · {2}",[e("input"===n?"입력":"출력"),o.label,typeLabels()[o.type||"any"]])),r.setAttribute("aria-pressed",String(!!o.connected));const a=this.el("span","port-dot");r.append(a);const d=this.el("span","port-label");d.textContent=o.label;const h=this.el("span","port-type");h.textContent=typeLabels()[o.type||"any"];const l={nodeId:this.nodeId(),portId:o.id,direction:n,type:o.type||"any"};r.addEventListener("click",()=>{this.suppressPortClick||this.dbEmit("port-select",l)}),r.addEventListener("pointerdown",t=>{0!==t.button||r.disabled||(this.portDrag={id:t.pointerId,button:r,port:l,x:t.clientX,y:t.clientY,moved:!1},this.suppressPortClick=!1,r.setPointerCapture(t.pointerId))}),r.addEventListener("pointermove",t=>{const e=this.portDrag;e&&e.id===t.pointerId&&(!e.moved&&Math.hypot(t.clientX-e.x,t.clientY-e.y)>=4&&(e.moved=!0,this.suppressPortClick=!0,this.emitPortDrag("start",e.x,e.y)),e.moved&&this.emitPortDrag("move",t.clientX,t.clientY))}),r.addEventListener("pointerup",t=>{this.portDrag?.id===t.pointerId&&(this.portDrag.moved&&this.emitPortDrag("end",t.clientX,t.clientY),this.portDrag=null,r.hasPointerCapture(t.pointerId)&&r.releasePointerCapture(t.pointerId),setTimeout(()=>{this.suppressPortClick=!1},0))}),r.addEventListener("pointercancel",()=>this.cancelPortDrag()),r.addEventListener("lostpointercapture",()=>this.cancelPortDrag()),r.addEventListener("keydown",t=>{"Escape"===t.key&&this.cancelPortDrag()}),s.append(r,d,h),i.append(s)}r&&this.getPortElement(r,n)?.focus({preventScroll:!0})}emitPortDrag(t,e,i){this.portDrag&&this.dbEmit("port-drag",{...this.portDrag.port,phase:t,clientX:e,clientY:i})}cancelPortDrag(){const t=this.portDrag;t&&(t.moved&&this.emitPortDrag("cancel",t.x,t.y),this.portDrag=null,t.button.hasPointerCapture(t.id)&&t.button.releasePointerCapture(t.id))}sync(){if(!this.headingButton)return;const t=this.hasAttribute("disabled"),e=this.hasAttribute("collapsed");this.setAttribute("aria-disabled",String(t)),this.root.querySelector(".frame").inert=t,this.dataset.variant=o.includes(this.getAttribute("variant"))?this.getAttribute("variant"):"default";const i=r.find(t=>t===this.getAttribute("status"))||"idle";this.dataset.status=i,this.titleEl.textContent=this.getAttribute("heading")||"새 노드",this.headingButton.disabled=t,this.headingButton.setAttribute("aria-pressed",String(this.hasAttribute("selected"))),this.headingButton.title=this.hasAttribute("movable")?"드래그 또는 방향키로 이동":"노드 선택";const n=this.getAttribute("icon");if(this.iconBox.hidden=!n,n?this.iconBox.replaceChildren(s(n,16)):this.iconBox.replaceChildren(),this.descriptionEl.textContent=this.getAttribute("description")||"",this.descriptionEl.hidden=e||!this.descriptionEl.textContent,this.statusBadge.textContent=d[i],this.statusBadge.setAttribute("variant","error"===i?"danger":"success"===i?"success":"info"),this.statusEl.hidden="idle"===i,this.collapseButton.hidden=!this.hasAttribute("collapsible"),this.collapseButton.disabled=t,this.collapseButton.setAttribute("aria-expanded",String(!e)),this.collapseButton.setAttribute("aria-label",e?"노드 펼치기":"노드 접기"),this.collapseButton.title=e?"노드 펼치기":"노드 접기",this.collapseButton.replaceChildren(s(e?"chevron-down":"chevron-up",16)),this.deleteButton.hidden=!this.hasAttribute("deletable"),this.deleteButton.disabled=t,this.runButton.hidden=!this.hasAttribute("runnable"),this.runButton.disabled=t||"running"===i,this.body.hidden=e||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=e||!this.footer.querySelector("slot").assignedNodes({flatten:!0}).length,this.portsDirty)this.renderPorts(this.inputList,this.inputPorts,"input"),this.renderPorts(this.outputList,this.outputPorts,"output"),this.portsDirty=!1;else for(const e of[this.inputList,this.outputList])for(const i of e.querySelectorAll("button")){const s=e===this.inputList?this.inputPorts:this.outputPorts;i.disabled=t||!!s.find(t=>t.id===i.dataset.portId)?.disabled}}}customElements.get("db-node")||customElements.define("db-node",DbNode);export{DbNode,r as NODE_STATUSES,o as NODE_VARIANTS};
|
|
1
|
+
import{subscribeDbLocale as t,dbFormat as e,dbText as i}from"../core/i18n.js";import{DbElement as s}from"../core/base-element.js";import{createDbIcon as n}from"./db-icons.js";import"./db-badge.js";import{nodeStyle as o}from"./node-style.js";import{NODE_VARIANTS as r,NODE_STATUSES as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const d=new Set(["any","text","image","number","boolean"]),typeLabels=()=>({any:i("일반"),text:i("텍스트"),image:i("이미지"),number:i("숫자"),boolean:i("조건")}),h={idle:"대기",running:"실행 중",success:"완료",error:"오류"};class DbNode extends s{constructor(){super(...arguments),this.root=this.attachShadow({mode:"open"}),this.inputPorts=[],this.outputPorts=[],this.portsDirty=!0,this.drag=null,this.portDrag=null,this.suppressPortClick=!1}static get observedAttributes(){return["node-id","heading","description","icon","variant","status","selected","collapsed","disabled","movable","runnable","collapsible","inputs","outputs","detail","deletable"]}get inputs(){return this.inputPorts.map(t=>({...t}))}set inputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.inputPorts)&&(this.inputPorts=e,this.portsDirty=!0,this.sync())}get outputs(){return this.outputPorts.map(t=>({...t}))}set outputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.outputPorts)&&(this.outputPorts=e,this.portsDirty=!0,this.sync())}getPortElement(t,e){const i="input"===e?this.inputList:this.outputList;return[...i?.querySelectorAll("button")||[]].find(e=>e.dataset.portId===t)||null}connectedCallback(){this.root.childElementCount||this.build(),this.upgradeProperties(["inputs","outputs"]);for(const t of["inputs","outputs"])this.hasAttribute(t)&&this.readPorts(t);this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>{this.sync();for(const[t,s,n]of[[this.inputList,this.inputPorts,"input"],[this.outputList,this.outputPorts,"output"]])for(const o of t.querySelectorAll("button")){const t=s.find(t=>t.id===o.dataset.portId);if(!t)continue;const r=typeLabels()[t.type||"any"];o.setAttribute("aria-label",e("{0} · {1} · {2}",[i("input"===n?"입력":"출력"),t.label,r]));const a=o.parentElement?.querySelector(".port-type");a&&(a.textContent=r)}}),this.sync()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.finishDrag("end"),this.cancelPortDrag(),super.disconnectedCallback()}attributeChangedCallback(t){"inputs"!==t&&"outputs"!==t||this.readPorts(t),"disabled"===t&&this.hasAttribute("disabled")&&(this.finishDrag("end"),this.cancelPortDrag()),this.sync()}normalizePorts(t){if(!Array.isArray(t))return[];const e=new Set;return t.filter(t=>t&&"string"==typeof t.id&&t.id&&"string"==typeof t.label&&!e.has(t.id)&&e.add(t.id)).map(t=>({id:t.id,label:t.label,type:d.has(t.type)?t.type:"any",connected:!!t.connected,disabled:!!t.disabled}))}readPorts(t){let e=[];try{e=JSON.parse(this.getAttribute(t)||"[]")}catch{}"inputs"===t?this.inputPorts=this.normalizePorts(e):this.outputPorts=this.normalizePorts(e),this.portsDirty=!0}nodeId(){return this.getAttribute("node-id")||this.id}el(t,e){const i=document.createElement(t);return i.className=e,i}action(t,e){const i=this.el("button","action");return i.type="button",i.setAttribute("aria-label",t),i.title=t,i.append(n(e,16)),i}build(){const t=document.createElement("style");t.textContent=o;const e=this.el("article","frame");e.part.add("frame");const i=this.el("header","header");i.part.add("header"),this.headingButton=this.el("button","heading"),this.headingButton.type="button",this.iconBox=this.el("span","icon"),this.iconBox.setAttribute("aria-hidden","true"),this.titleEl=this.el("span","title"),this.headingButton.append(this.iconBox,this.titleEl),this.statusEl=this.el("span","status"),this.statusEl.setAttribute("role","status"),this.statusBadge=document.createElement("db-badge"),this.statusBadge.setAttribute("size","s"),this.statusBadge.setAttribute("type","outlined"),this.statusEl.append(this.statusBadge);const s=this.el("div","actions"),n=document.createElement("slot");n.name="actions",this.runButton=this.action("노드 실행","play-outline"),this.runButton.classList.add("action--run"),this.collapseButton=this.action("노드 접기","chevron-up"),this.deleteButton=this.action("노드 삭제","close"),this.deleteButton.addEventListener("click",()=>this.dbEmit("delete",{nodeId:this.nodeId()},{cancelable:!0})),s.append(n,this.runButton,this.collapseButton,this.deleteButton),i.append(this.headingButton,this.statusEl,s),this.descriptionEl=this.el("p","description"),this.inputList=this.el("div","ports ports--input"),this.inputList.part.add("inputs"),this.outputList=this.el("div","ports ports--output"),this.outputList.part.add("outputs"),this.body=this.el("div","body"),this.body.part.add("body"),this.body.append(document.createElement("slot")),this.footer=this.el("footer","footer");const r=document.createElement("slot");r.name="footer",this.footer.append(r);this.root.addEventListener("slotchange",()=>{this.body.hidden=this.hasAttribute("collapsed")||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=this.hasAttribute("collapsed")||!r.assignedNodes({flatten:!0}).length}),e.append(i,this.descriptionEl,this.inputList,this.body,this.outputList,this.footer),this.root.append(t,e);const isEditor=t=>t.composedPath().some(t=>t instanceof HTMLElement&&(t.isContentEditable||t.matches("input, textarea, db-input, db-textarea, db-markdown-editor")));this.addEventListener("selectstart",t=>{isEditor(t)||t.preventDefault()}),this.addEventListener("dragstart",t=>{isEditor(t)||t.preventDefault()}),this.headingButton.addEventListener("click",()=>{this.hasAttribute("disabled")||this.dbEmit("select",{nodeId:this.nodeId()})}),this.collapseButton.addEventListener("click",()=>{const t=!this.hasAttribute("collapsed");this.toggleAttribute("collapsed",t),this.dbEmit("collapse",{nodeId:this.nodeId(),collapsed:t})}),this.runButton.addEventListener("click",()=>this.dbEmit("run",{nodeId:this.nodeId()},{cancelable:!0})),this.headingButton.addEventListener("pointerdown",t=>{this.hasAttribute("movable")&&!this.hasAttribute("disabled")&&0===t.button&&(this.drag={id:t.pointerId,x:t.clientX,y:t.clientY,lastX:t.clientX,lastY:t.clientY},this.headingButton.setPointerCapture(t.pointerId),this.emitMove("start",0,0))}),this.headingButton.addEventListener("pointermove",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.emitMove("move",t.clientX-this.drag.x,t.clientY-this.drag.y))}),this.headingButton.addEventListener("pointerup",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.finishDrag("end"))}),this.headingButton.addEventListener("pointercancel",()=>this.finishDrag("end")),this.headingButton.addEventListener("lostpointercapture",()=>this.finishDrag("end")),this.headingButton.addEventListener("keydown",t=>{if("Escape"===t.key&&this.drag)return void this.finishDrag("cancel");if(!this.hasAttribute("movable")||this.hasAttribute("disabled"))return;const e={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};if(e[t.key]){t.preventDefault();const[i,s]=e[t.key],n=t.shiftKey?4:16;this.emitMove("keyboard",i*n,s*n)}})}emitMove(t,e,i){this.dbEmit("move",{nodeId:this.nodeId(),deltaX:e,deltaY:i,phase:t})}finishDrag(t){const e=this.drag;e&&(this.drag=null,this.emitMove(t,"cancel"===t?0:e.lastX-e.x,"cancel"===t?0:e.lastY-e.y),this.headingButton.hasPointerCapture(e.id)&&this.headingButton.releasePointerCapture(e.id))}renderPorts(t,s,n){const o=this.root.activeElement,r=o&&t.contains(o)?o.dataset.portId:void 0;this.cancelPortDrag(),t.replaceChildren(),t.hidden=!s.length;for(const o of s){const s=this.el("div","port-row");s.dataset.type=o.type||"any";const r=this.el("button","port");r.type="button",r.part.add("port"),r.dataset.portId=o.id,r.dataset.direction=n,r.disabled=this.hasAttribute("disabled")||!!o.disabled,r.dataset.connected=String(!!o.connected),r.setAttribute("aria-label",e("{0} · {1} · {2}",[i("input"===n?"입력":"출력"),o.label,typeLabels()[o.type||"any"]])),r.setAttribute("aria-pressed",String(!!o.connected));const a=this.el("span","port-dot");r.append(a);const d=this.el("span","port-label");d.textContent=o.label;const h=this.el("span","port-type");h.textContent=typeLabels()[o.type||"any"];const l={nodeId:this.nodeId(),portId:o.id,direction:n,type:o.type||"any"};r.addEventListener("click",()=>{this.suppressPortClick||this.dbEmit("port-select",l)}),r.addEventListener("pointerdown",t=>{0!==t.button||r.disabled||(this.portDrag={id:t.pointerId,button:r,port:l,x:t.clientX,y:t.clientY,moved:!1},this.suppressPortClick=!1,r.setPointerCapture(t.pointerId))}),r.addEventListener("pointermove",t=>{const e=this.portDrag;e&&e.id===t.pointerId&&(!e.moved&&Math.hypot(t.clientX-e.x,t.clientY-e.y)>=4&&(e.moved=!0,this.suppressPortClick=!0,this.emitPortDrag("start",e.x,e.y)),e.moved&&this.emitPortDrag("move",t.clientX,t.clientY))}),r.addEventListener("pointerup",t=>{this.portDrag?.id===t.pointerId&&(this.portDrag.moved&&this.emitPortDrag("end",t.clientX,t.clientY),this.portDrag=null,r.hasPointerCapture(t.pointerId)&&r.releasePointerCapture(t.pointerId),setTimeout(()=>{this.suppressPortClick=!1},0))}),r.addEventListener("pointercancel",()=>this.cancelPortDrag()),r.addEventListener("lostpointercapture",()=>this.cancelPortDrag()),r.addEventListener("keydown",t=>{"Escape"===t.key&&this.cancelPortDrag()}),s.append(r,d,h),t.append(s)}r&&this.getPortElement(r,n)?.focus({preventScroll:!0})}emitPortDrag(t,e,i){this.portDrag&&this.dbEmit("port-drag",{...this.portDrag.port,phase:t,clientX:e,clientY:i})}cancelPortDrag(){const t=this.portDrag;t&&(t.moved&&this.emitPortDrag("cancel",t.x,t.y),this.portDrag=null,t.button.hasPointerCapture(t.id)&&t.button.releasePointerCapture(t.id))}sync(){if(!this.headingButton)return;const t=this.hasAttribute("disabled"),e=this.hasAttribute("collapsed");this.setAttribute("aria-disabled",String(t)),this.root.querySelector(".frame").inert=t,this.dataset.variant=r.includes(this.getAttribute("variant"))?this.getAttribute("variant"):"default";const s=a.find(t=>t===this.getAttribute("status"))||"idle";this.dataset.status=s,this.titleEl.textContent=this.getAttribute("heading")||i("새 노드"),this.headingButton.disabled=t,this.headingButton.setAttribute("aria-pressed",String(this.hasAttribute("selected"))),this.headingButton.title=i(this.hasAttribute("movable")?"드래그 또는 방향키로 이동":"노드 선택");const o=this.getAttribute("icon");if(this.iconBox.hidden=!o,o?this.iconBox.replaceChildren(n(o,16)):this.iconBox.replaceChildren(),this.descriptionEl.textContent=this.getAttribute("description")||"",this.descriptionEl.hidden=e||!this.descriptionEl.textContent,this.statusBadge.textContent=i(h[s]),this.statusBadge.setAttribute("variant","error"===s?"danger":"success"===s?"success":"info"),this.statusEl.hidden="idle"===s,this.collapseButton.hidden=!this.hasAttribute("collapsible"),this.collapseButton.disabled=t,this.collapseButton.setAttribute("aria-expanded",String(!e)),this.collapseButton.setAttribute("aria-label",i(e?"노드 펼치기":"노드 접기")),this.collapseButton.title=i(e?"노드 펼치기":"노드 접기"),this.collapseButton.replaceChildren(n(e?"chevron-down":"chevron-up",16)),this.deleteButton.hidden=!this.hasAttribute("deletable"),this.deleteButton.disabled=t,this.runButton.hidden=!this.hasAttribute("runnable"),this.runButton.disabled=t||"running"===s,this.deleteButton.title=i("노드 삭제"),this.deleteButton.setAttribute("aria-label",this.deleteButton.title),this.runButton.title=i("노드 실행"),this.runButton.setAttribute("aria-label",this.runButton.title),this.body.hidden=e||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=e||!this.footer.querySelector("slot").assignedNodes({flatten:!0}).length,this.portsDirty)this.renderPorts(this.inputList,this.inputPorts,"input"),this.renderPorts(this.outputList,this.outputPorts,"output"),this.portsDirty=!1;else for(const e of[this.inputList,this.outputList])for(const i of e.querySelectorAll("button")){const s=e===this.inputList?this.inputPorts:this.outputPorts;i.disabled=t||!!s.find(t=>t.id===i.dataset.portId)?.disabled}}}customElements.get("db-node")||customElements.define("db-node",DbNode);export{DbNode,a as NODE_STATUSES,r as NODE_VARIANTS};
|
|
@@ -6,6 +6,7 @@ type OnboardingStep = {
|
|
|
6
6
|
};
|
|
7
7
|
declare class DbOnboardingModal extends HTMLElement {
|
|
8
8
|
static get observedAttributes(): string[];
|
|
9
|
+
private unsubscribeLocale?;
|
|
9
10
|
private root?;
|
|
10
11
|
private focusTrap?;
|
|
11
12
|
/** 참조 카운트 스크롤락을 이 인스턴스가 잡고 있는지 (PERF-GLOBAL-STATE) */
|
|
@@ -49,6 +50,7 @@ declare class DbOnboardingModal extends HTMLElement {
|
|
|
49
50
|
private mount;
|
|
50
51
|
private unmount;
|
|
51
52
|
private ensureStructure;
|
|
53
|
+
private syncLocale;
|
|
52
54
|
private render;
|
|
53
55
|
}
|
|
54
56
|
declare global {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as
|
|
1
|
+
import{inheritThemeScope as t}from"../core/theme-scope.js";import{subscribeDbLocale as e,dbText as i}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{createFocusTrap as n}from"../core/focus-trap.js";import{lockScroll as o,unlockScroll as r}from"../core/scroll-lock.js";class DbOnboardingModal extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.internalStep=0,this.keyHandler=null,this.isMounted=!1,this.handlePrev=()=>{this.getCurrentStep()>0&&this.goToStep(this.getCurrentStep()-1)},this.handleNext=()=>{const t=this.getSteps(),e=this.getCurrentStep();e>=t.length-1?this.dispatchEvent(new CustomEvent("db-complete",{bubbles:!0,composed:!0})):this.goToStep(e+1)}}static get observedAttributes(){return["open","steps","current-step","show-close-button","show-indicator","indicator-type","indicator-size"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}get steps(){return this.parseSteps()}set steps(t){const e="string"==typeof t?t:JSON.stringify(t);this.getAttribute("steps")!==e&&this.setAttribute("steps",e)}connectedCallback(){this.style.display="contents",this.syncStepFromAttribute(),this.syncOpenState(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.detachKeyHandler(),this.unmount()}attributeChangedCallback(t){this.isConnected&&("open"!==t?("current-step"===t&&this.syncStepFromAttribute(),"steps"!==t?this.isMounted&&this.render():this.isOpenRequested()&&(this.isMounted?this.render():this.syncOpenState())):this.syncOpenState())}isOpenRequested(){return this.open}parseSteps(){const t=this.getAttribute("steps");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}syncStepFromAttribute(){if(!this.hasAttribute("current-step"))return;const t=Number(this.getAttribute("current-step")||0);Number.isFinite(t)&&(this.internalStep=Math.max(0,t))}getSteps(){return this.parseSteps()}getCurrentStep(){const t=this.getSteps();return t.length?Math.min(Math.max(this.internalStep,0),t.length-1):0}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}emitStepChange(t){this.dispatchEvent(new CustomEvent("db-step-change",{bubbles:!0,composed:!0,detail:{step:t}}))}goToStep(t){const e=this.getSteps();if(!e.length)return;const i=Math.min(Math.max(t,0),e.length-1);this.internalStep=i,this.emitStepChange(i),this.render()}attachKeyHandler(){this.keyHandler||(this.keyHandler=t=>{"Escape"!==t.key?"ArrowLeft"===t.key&&this.getCurrentStep()>0?this.handlePrev():"ArrowRight"===t.key&&this.getCurrentStep()<this.getSteps().length-1&&this.handleNext():this.close()},document.addEventListener("keydown",this.keyHandler))}detachKeyHandler(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}syncOpenState(){if(this.isOpenRequested())return this.mount(),void this.attachKeyHandler();this.detachKeyHandler(),this.unmount()}mount(){this.root||(this.root=document.createElement("div"),this.root.className="designbase-wc-onboarding-modal",this.root.setAttribute("role","dialog"),this.root.setAttribute("aria-modal","true"),this.root.tabIndex=-1,this.ensureStructure()),this.root.isConnected||(t(this,this.root),document.body.append(this.root)),this.isMounted=!0,this.render(),this.scrollLocked||(o(),this.scrollLocked=!0),this.root&&!this.focusTrap&&(this.focusTrap=n(this.root),requestAnimationFrame(()=>this.focusTrap?.activate()))}unmount(){this.isMounted=!1,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.root?.remove(),this.scrollLocked&&(this.scrollLocked=!1,r())}ensureStructure(){this.root&&(this.contentEl&&this.root.contains(this.contentEl)||(this.overlayEl=void 0,this.contentEl=void 0,this.closeButtonEl=void 0,this.mainEl=void 0,this.imageWrapEl=void 0,this.imageEl=void 0,this.textEl=void 0,this.titleEl=void 0,this.descriptionEl=void 0,this.navigationEl=void 0,this.prevButtonEl=void 0,this.nextButtonEl=void 0,this.indicatorEl=void 0,this.root.replaceChildren(),this.overlayEl=document.createElement("div"),this.overlayEl.className="designbase-wc-onboarding-modal__overlay",this.overlayEl.addEventListener("click",()=>this.close()),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-onboarding-modal__content",this.closeButtonEl=document.createElement("button"),this.closeButtonEl.type="button",this.closeButtonEl.className="designbase-wc-onboarding-modal__close-button",this.closeButtonEl.setAttribute("aria-label",i("닫기")),this.closeButtonEl.append(s("close",20)),this.closeButtonEl.addEventListener("click",()=>this.close()),this.mainEl=document.createElement("div"),this.mainEl.className="designbase-wc-onboarding-modal__main",this.imageWrapEl=document.createElement("div"),this.imageWrapEl.className="designbase-wc-onboarding-modal__image",this.imageEl=document.createElement("img"),this.imageWrapEl.append(this.imageEl),this.textEl=document.createElement("div"),this.textEl.className="designbase-wc-onboarding-modal__text",this.titleEl=document.createElement("h2"),this.titleEl.id="onboarding-title",this.titleEl.className="designbase-wc-onboarding-modal__title",this.descriptionEl=document.createElement("p"),this.descriptionEl.id="onboarding-description",this.descriptionEl.className="designbase-wc-onboarding-modal__description",this.textEl.append(this.titleEl,this.descriptionEl),this.mainEl.append(this.imageWrapEl,this.textEl),this.navigationEl=document.createElement("div"),this.navigationEl.className="designbase-wc-onboarding-modal__navigation",this.prevButtonEl=document.createElement("db-button"),this.prevButtonEl.setAttribute("variant","secondary"),this.prevButtonEl.setAttribute("size","m"),this.prevButtonEl.setAttribute("start-icon","chevron-left"),this.prevButtonEl.setAttribute("aria-label",i("이전")),this.prevButtonEl.addEventListener("db-click",this.handlePrev),this.indicatorEl=document.createElement("db-indicator"),this.indicatorEl.addEventListener("db-step-click",t=>{const e=t.detail;this.goToStep(e.index??e.current)}),this.nextButtonEl=document.createElement("db-button"),this.nextButtonEl.setAttribute("variant","primary"),this.nextButtonEl.setAttribute("size","m"),this.nextButtonEl.addEventListener("db-click",this.handleNext),this.navigationEl.append(this.prevButtonEl,this.indicatorEl,this.nextButtonEl),this.contentEl.append(this.closeButtonEl,this.mainEl,this.navigationEl),this.root.append(this.overlayEl,this.contentEl)))}syncLocale(){this.closeButtonEl?.setAttribute("aria-label",i("닫기")),this.prevButtonEl?.setAttribute("aria-label",i("이전")),this.prevButtonEl&&(this.prevButtonEl.textContent=i("이전"));const t=this.getSteps(),e=this.getCurrentStep(),s=i(e===t.length-1?"완료":"다음");this.nextButtonEl&&(this.nextButtonEl.textContent=s,this.nextButtonEl.setAttribute("aria-label",s)),this.imageEl&&t[e]?.image&&!t[e]?.title&&(this.imageEl.alt=i("온보딩 이미지"))}render(){if(!this.root||!this.isMounted)return;this.ensureStructure();const t=this.getSteps(),e=this.getCurrentStep(),s=t[e];if(!s)return;const n=!this.hasAttribute("show-close-button")||"false"!==this.getAttribute("show-close-button"),o=!this.hasAttribute("show-indicator")||"false"!==this.getAttribute("show-indicator"),r=this.getAttribute("indicator-type")||"dots",l=this.getAttribute("indicator-size")||"m",a=0===e,h=e===t.length-1;if(this.root.setAttribute("aria-labelledby","onboarding-title"),this.root.setAttribute("aria-describedby","onboarding-description"),this.closeButtonEl&&(this.closeButtonEl.style.display=n?"":"none"),this.imageWrapEl&&this.imageEl&&(s.image?(this.imageEl.src=s.image,this.imageEl.alt=s.title||i("온보딩 이미지"),this.imageWrapEl.style.display=""):this.imageWrapEl.style.display="none"),this.titleEl&&(this.titleEl.textContent=s.title||"",this.titleEl.style.display=s.title?"":"none"),this.descriptionEl&&(this.descriptionEl.textContent=s.description||"",this.descriptionEl.style.display=s.description?"":"none"),this.prevButtonEl&&(this.prevButtonEl.textContent=i("이전"),a?this.prevButtonEl.setAttribute("disabled",""):this.prevButtonEl.removeAttribute("disabled")),this.nextButtonEl&&(this.nextButtonEl.textContent=i(h?"완료":"다음"),this.nextButtonEl.setAttribute("aria-label",i(h?"완료":"다음")),h?this.nextButtonEl.removeAttribute("end-icon"):this.nextButtonEl.setAttribute("end-icon","chevron-right")),this.indicatorEl){const i=o&&t.length>1;this.indicatorEl.style.display=i?"":"none",i&&(this.indicatorEl.setAttribute("total",String(t.length)),this.indicatorEl.setAttribute("current",String(e)),this.indicatorEl.setAttribute("indicator-type",r),this.indicatorEl.setAttribute("size",l),this.indicatorEl.setAttribute("clickable",""))}}}customElements.get("db-onboarding-modal")||customElements.define("db-onboarding-modal",DbOnboardingModal);export{DbOnboardingModal};
|
|
@@ -11,6 +11,7 @@ declare class DbOtpInput extends HTMLElement {
|
|
|
11
11
|
static get observedAttributes(): string[];
|
|
12
12
|
private internals;
|
|
13
13
|
private built;
|
|
14
|
+
private unsubscribeLocale?;
|
|
14
15
|
private digits;
|
|
15
16
|
private errorEl?;
|
|
16
17
|
private suppressSync;
|
|
@@ -27,12 +28,14 @@ declare class DbOtpInput extends HTMLElement {
|
|
|
27
28
|
get readOnly(): boolean;
|
|
28
29
|
set readOnly(v: boolean);
|
|
29
30
|
connectedCallback(): void;
|
|
30
|
-
|
|
31
|
+
disconnectedCallback(): void;
|
|
32
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
31
33
|
focus(): void;
|
|
32
34
|
clear(): void;
|
|
33
35
|
formResetCallback(): void;
|
|
34
36
|
formDisabledCallback(disabled: boolean): void;
|
|
35
37
|
private build;
|
|
38
|
+
private refreshLocale;
|
|
36
39
|
private sync;
|
|
37
40
|
private emit;
|
|
38
41
|
private setValueAttribute;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbFormat as
|
|
1
|
+
import{subscribeDbLocale as t,dbText as e,dbFormat as i}from"../core/i18n.js";import{dbUid as s}from"../core/uid.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{OTP_INPUT_SIZES as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbOtpInput extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals?.(),this.built=!1,this.digits=[],this.suppressSync=!1,this.initialValue="",this.lastCompleteValue="",this.onDigitFocus=t=>{const e=t.currentTarget;requestAnimationFrame(()=>e.select())},this.onDigitInput=t=>{if(this.suppressSync)return;const e=t.currentTarget,i=Number(e.dataset.index||0),s=e.value.replace(/\D/g,"");if(s.length>1){const t=this.digits.slice(0,i).map(t=>t.value).join("");return void this.applyValue(t+s,Math.min(this.length-1,t.length+s.length))}e.value=s.slice(-1),e.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(e.value));const a=this.digits.map(t=>t.value).join("");this.setAttribute("value",a),this.emit("db-input"),this.emit("db-change"),e.value&&i<this.digits.length-1&&this.focusAt(i+1)},this.onDigitKeydown=t=>{const e=t.currentTarget,i=Number(e.dataset.index||0);if("Backspace"!==t.key)return"ArrowLeft"===t.key?(t.preventDefault(),void this.focusAt(i-1)):"ArrowRight"===t.key?(t.preventDefault(),void this.focusAt(i+1)):void("Delete"===t.key&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change")));if(e.value)e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change");else if(i>0){t.preventDefault(),this.focusAt(i-1);const e=this.digits[i-1];e&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change"))}},this.onPaste=t=>{t.preventDefault();const e=t.clipboardData?.getData("text")||"",i=Number(t.currentTarget.dataset.index||0),s=this.digits.slice(0,i).map(t=>t.value).join("");this.applyValue(s+e,Math.min(this.length-1,s.length+e.replace(/\D/g,"").length))}}static get observedAttributes(){return["length","value","size","disabled","readonly","error","error-message","label","auto-focus","masked","name","required","full-width"]}get length(){const t=Number(this.getAttribute("length")||6);return Number.isFinite(t)?Math.min(8,Math.max(4,Math.round(t))):6}set length(t){this.setAttribute("length",String(t))}get value(){return this.digits.map(t=>t.value).join("")||this.getAttribute("value")||""}set value(t){this.setAttribute("value",t)}get size(){return a(this.getAttribute("size"),l,"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(){this.built||(this.initialValue=this.getAttribute("value")||""),this.build(),this.sync(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.refreshLocale()),this.hasAttribute("auto-focus")&&!this.disabled&&requestAnimationFrame(()=>this.focusFirstEmpty())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(t,e,i){this.built&&e!==i&&("length"===t&&(this.built=!1,this.build()),this.sync())}focus(){this.disabled||this.focusFirstEmpty()}clear(){this.suppressSync=!0,this.digits.forEach(t=>{t.value=""}),this.suppressSync=!1,this.lastCompleteValue="",this.setValueAttribute(""),this.emit("db-input"),this.emit("db-change"),this.focusFirstEmpty()}formResetCallback(){this.lastCompleteValue="",this.value=this.initialValue}formDisabledCallback(t){this.toggleAttribute("disabled",t)}build(){this.replaceChildren(),this.digits=[];const t=this.length,a="designbase-wc-otp-input",l=this.getAttribute("label");if(l){const t=el("div",`${a}__label`);t.textContent=l,this.append(t)}const r=el("div",`${a}__row`);r.setAttribute("role","group"),r.setAttribute("aria-label",l||e("인증 코드"));for(let e=0;e<t;e+=1){const t=el("div",`${a}__cell`),s=document.createElement("input");s.className=`${a}__digit`,s.type=this.hasAttribute("masked")?"password":"text",s.inputMode="numeric",s.autocomplete=0===e?"one-time-code":"off",s.maxLength=1,s.pattern="[0-9]*",s.setAttribute("aria-label",i("{0}번째 자리",[e+1])),s.dataset.index=String(e),s.addEventListener("input",this.onDigitInput),s.addEventListener("keydown",this.onDigitKeydown),s.addEventListener("paste",this.onPaste),s.addEventListener("focus",this.onDigitFocus),t.append(s),r.append(t),this.digits.push(s)}this.append(r),this.errorEl=el("p",`${a}__error`),this.errorEl.id=`${this.id||s("db-otp")}-error`,this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,this.append(this.errorEl),this.built=!0}refreshLocale(){this.querySelector(".designbase-wc-otp-input__row")?.setAttribute("aria-label",this.getAttribute("label")||e("인증 코드")),this.digits.forEach((t,e)=>t.setAttribute("aria-label",i("{0}번째 자리",[e+1]))),this.syncFormValue(this.digits.map(t=>t.value).join(""))}sync(){const t="designbase-wc-otp-input",e=this.size,i=this.hasAttribute("error"),s=this.disabled,a=this.readOnly,l=this.getAttribute("error-message")||"";this.className=[t,`${t}--${e}`,i&&`${t}--error`,s&&`${t}--disabled`,this.hasAttribute("full-width")&&`${t}--full-width`].filter(Boolean).join(" ");const r=(this.getAttribute("value")||"").replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((e,n)=>{e.value=r[n]||"",e.disabled=s,e.readOnly=a,e.type=this.hasAttribute("masked")?"password":"text",e.classList.toggle(`${t}__digit--filled`,Boolean(e.value)),e.setAttribute("aria-invalid",String(i)),i&&l?e.setAttribute("aria-describedby",this.errorEl?.id||""):e.removeAttribute("aria-describedby")}),this.suppressSync=!1,this.errorEl&&(this.errorEl.textContent=l,this.errorEl.hidden=!i||!l),this.setAttribute("role","group"),this.setAttribute("aria-disabled",String(s)),this.setAttribute("aria-invalid",String(i)),this.syncFormValue(r)}emit(t){const e=this.digits.map(t=>t.value).join("");if(this.setValueAttribute(e),this.dispatchEvent(new CustomEvent(t,{detail:{value:e},bubbles:!0,composed:!0})),"db-change"===t&&e.length===this.length&&/^\d+$/.test(e)){if(e===this.lastCompleteValue)return;this.lastCompleteValue=e,this.dispatchEvent(new CustomEvent("db-complete",{detail:{value:e},bubbles:!0,composed:!0}))}else e.length!==this.length&&(this.lastCompleteValue="")}setValueAttribute(t){this.getAttribute("value")!==t&&this.setAttribute("value",t),this.syncFormValue(t)}syncFormValue(t){this.internals?.setFormValue(t||null),this.internals&&(this.hasAttribute("error")?this.internals.setValidity({customError:!0},this.getAttribute("error-message")||e("인증 코드가 올바르지 않습니다."),this.digits[0]):this.hasAttribute("required")&&t.length!==this.length?this.internals.setValidity({valueMissing:!0},e("인증 코드를 모두 입력해 주세요."),this.digits.find(t=>!t.value)||this.digits[0]):this.internals.setValidity({}))}focusFirstEmpty(){const t=this.digits.find(t=>!t.value)||this.digits[this.digits.length-1];t?.focus(),t?.select()}focusAt(t){const e=this.digits[Math.max(0,Math.min(this.digits.length-1,t))];e?.focus(),e?.select()}applyValue(t,e){const i=t.replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((t,e)=>{t.value=i[e]||"",t.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(t.value))}),this.suppressSync=!1,this.emit("db-input"),this.emit("db-change"),void 0!==e?this.focusAt(e):i.length<this.length?this.focusAt(i.length):this.focusAt(this.length-1)}}DbOtpInput.formAssociated=!0,customElements.get("db-otp-input")||customElements.define("db-otp-input",DbOtpInput);export{DbOtpInput};
|