@designbasekorea/ui-wc 0.9.2 → 0.9.4
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 +22 -0
- package/dist/esm/components/date-picker-utils.js +1 -1
- package/dist/esm/components/db-activity-heatmap.js +1 -1
- package/dist/esm/components/db-ai-chat-list.js +1 -1
- package/dist/esm/components/db-ai-file-tree.js +1 -1
- package/dist/esm/components/db-alert.d.ts +12 -0
- package/dist/esm/components/db-alert.js +1 -1
- package/dist/esm/components/db-backdrop.js +1 -1
- package/dist/esm/components/db-bottom-sheet.js +1 -1
- package/dist/esm/components/db-calendar.d.ts +2 -1
- package/dist/esm/components/db-calendar.js +1 -1
- package/dist/esm/components/db-carousel.d.ts +2 -0
- package/dist/esm/components/db-carousel.js +1 -1
- package/dist/esm/components/db-chat-composer.js +1 -1
- package/dist/esm/components/db-checkbox.d.ts +15 -1
- package/dist/esm/components/db-checkbox.js +1 -1
- package/dist/esm/components/db-code-block.js +1 -1
- package/dist/esm/components/db-confirm.d.ts +2 -0
- package/dist/esm/components/db-confirm.js +1 -1
- package/dist/esm/components/db-context-menu.js +1 -1
- package/dist/esm/components/db-credit-card.d.ts +3 -4
- package/dist/esm/components/db-credit-card.js +1 -1
- package/dist/esm/components/db-cursor-follower.js +1 -1
- package/dist/esm/components/db-date-picker.d.ts +2 -1
- package/dist/esm/components/db-date-picker.js +1 -1
- package/dist/esm/components/db-design-toolbar.js +1 -1
- package/dist/esm/components/db-device-mockup.js +1 -1
- package/dist/esm/components/db-drawer.d.ts +1 -0
- package/dist/esm/components/db-drawer.js +1 -1
- package/dist/esm/components/db-dropdown.js +1 -1
- package/dist/esm/components/db-flight-status.d.ts +2 -2
- package/dist/esm/components/db-flight-status.js +1 -1
- package/dist/esm/components/db-gantt.js +1 -1
- package/dist/esm/components/db-indicator.d.ts +1 -0
- package/dist/esm/components/db-indicator.js +1 -1
- package/dist/esm/components/db-kanban.js +1 -1
- package/dist/esm/components/db-lightbox.js +1 -1
- package/dist/esm/components/db-modal.js +1 -1
- package/dist/esm/components/db-node.d.ts +1 -3
- package/dist/esm/components/db-node.js +1 -1
- package/dist/esm/components/db-onboarding-modal.js +1 -1
- package/dist/esm/components/db-popover.js +1 -1
- package/dist/esm/components/db-radio.d.ts +19 -1
- package/dist/esm/components/db-radio.js +1 -1
- package/dist/esm/components/db-receipt.js +1 -1
- package/dist/esm/components/db-search-bar.js +1 -1
- package/dist/esm/components/db-select.js +1 -1
- package/dist/esm/components/db-tabs.js +1 -1
- package/dist/esm/components/db-textarea.js +1 -1
- package/dist/esm/components/db-time-picker.js +1 -1
- package/dist/esm/components/db-tool-button.js +1 -1
- package/dist/esm/components/db-tooltip.js +1 -1
- package/dist/esm/components/db-tutorial.js +1 -1
- package/dist/esm/components/db-voice-control.js +1 -1
- package/dist/esm/core/ai-element.d.ts +2 -1
- package/dist/esm/core/ai-element.js +1 -1
- package/dist/esm/core/focus-trap.js +1 -1
- package/dist/esm/core/host-class.js +1 -0
- 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 +16 -0
- package/dist/esm/core/i18n.js +1 -1
- package/dist/esm/core/theme-scope.js +1 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/esm/ui-contracts/dist/components.d.d.ts +9 -2
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +83 -13
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +35 -9
- package/dist/react/index.esm.js +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# 변경 이력
|
|
2
2
|
|
|
3
|
+
## 0.9.4 - 2026-10-27
|
|
4
|
+
|
|
5
|
+
Workspace 템플릿 인박스·프로젝트 탭에서 발견한 레이아웃 버그 수정 릴리스입니다.
|
|
6
|
+
|
|
7
|
+
- Tabs: 패널 콘텐츠(슬롯) 없이 탭을 내비게이션으로만 쓸 때(`items` + `onChange`로 내용을 바깥에서 렌더) 빈 패널 박스가 패딩·배경과 함께 그려져 탭 아래 흰 여백이 생기던 문제 수정. 패널이 하나도 없으면 패널을 숨기고 `aria-controls`도 붙이지 않습니다(`designbase-wc-tabs--nav-only`).
|
|
8
|
+
- Textarea: `rows`를 지정해도 `min-height: 100px` 때문에 높이가 줄지 않던 문제 수정. `rows`를 주면 그 줄 수가 높이를 결정하고, 주지 않으면 기존 기본 높이를 유지합니다.
|
|
9
|
+
- Textarea: 도움말·오류·글자 수가 모두 없을 때 하단 푸터(20px)를 숨겨 필드 아래 빈 여백이 생기지 않습니다.
|
|
10
|
+
- Avatar: flex 행에서 긴 텍스트 옆에 놓이면 가로로 눌려 원이 찌그러지던 문제 수정(`flex-shrink: 0`).
|
|
11
|
+
|
|
12
|
+
## 0.9.3 - 2026-10-26
|
|
13
|
+
|
|
14
|
+
Pro 템플릿(AI Assistant·Docs) 제작 중 발견한 라이브러리 버그 수정 릴리스입니다.
|
|
15
|
+
|
|
16
|
+
- ChatComposer: 전송·정지·첨부 버튼 접근성 이름과 placeholder 기본값이 `dbUseLocale('en')`을 따르도록 i18n 키(`chatComposer.*`)로 이동. `send-label`이 실제로 전송 버튼에 적용되고, `stop-label`·`attach-label`(React `stopLabel`·`attachLabel`)을 추가. 드롭 오버레이 문구도 번역됩니다.
|
|
17
|
+
- VoiceControl: 시작·완료·취소 라벨과 상태 문구를 i18n 키(`voice.*`)로 이동. `start-label`·`stop-label`·`cancel-label`은 계속 우선합니다.
|
|
18
|
+
- i18n: 영어 로케일에서 `dbText('첨부')`가 "Added"로 나오던 번역 오류를 "Attach"로 수정. "~ 추가" 버튼 문구("Add color" 등)와 첨부 메뉴·음성 입력 문구의 영어 번역도 바로잡음.
|
|
19
|
+
- Select, Dropdown, AiChatList, CodeBlock, ChatComposer, Alert: 렌더할 때 호스트의 `class`를 통째로 덮어써 소비자 클래스(React `className` 포함)가 사라지던 문제 수정. 컴포넌트는 자기 클래스만 추가·제거합니다(`core/host-class`).
|
|
20
|
+
- Alert: 자식 콘텐츠(링크·`code`·텍스트 등)를 본문 아래 슬롯에 렌더합니다. 재렌더해도 유지되고 나중에 추가된 자식도 반영됩니다. React `<Alert>`는 순수 텍스트 자식은 기존처럼 `message`로, 요소가 섞인 자식은 실제 DOM으로 전달합니다.
|
|
21
|
+
- **동작 변경** Alert: 닫기 버튼이 옵트인으로 바뀌었습니다. `closable` 속성(React `closable`)을 줄 때만 표시합니다. 이전처럼 닫기 버튼이 필요하면 `closable`을 추가하세요.
|
|
22
|
+
- 호스트 클래스: React `className`이 나중에 바뀌어 class 속성이 다시 쓰여도 컴포넌트 소유 클래스를 즉시 복원합니다.
|
|
23
|
+
- 회귀 테스트: `npm run test:template-fixes` (`scripts/test-ui-wc-template-fixes.mjs`, 빌드된 dist를 Chromium에서 검증).
|
|
24
|
+
|
|
3
25
|
## 0.9.2 - 2026-10-24
|
|
4
26
|
|
|
5
27
|
`@designbasekorea/ui-wc` 컴포넌트 패키지 단독 릴리스입니다. 현재 WC/React 컴포넌트와 스타일·타입 선언을 재빌드하며 examples, blocks, 페이지 템플릿은 배포 대상에 포함하지 않습니다.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as t,getDbLocale as e}from"../core/i18n.js";const startOfDay=t=>{const e=new Date(t);return e.setHours(0,0,0,0),e},endOfDay=t=>{const e=new Date(t);return e.setHours(23,59,59,999),e},addDays=(t,e)=>{const n=new Date(t);return n.setDate(n.getDate()+e),startOfDay(n)},getMonthEnd=t=>endOfDay(new Date(t.getFullYear(),t.getMonth()+1,0)),getYearEnd=t=>endOfDay(new Date(t.getFullYear(),11,31)),clampRange=(t,e,n)=>{let{start:a,end:r}=t;return e&&a<e&&(a=startOfDay(e)),n&&r>n&&(r=endOfDay(n)),a>r?{start:r,end:a}:{start:a,end:r}},n=[{id:"today",label:t("오늘"),getRange:({today:t})=>clampRange({start:startOfDay(t),end:endOfDay(t)})},{id:"yesterday",label:t("어제"),getRange:({today:t})=>{const e=addDays(t,-1);return clampRange({start:e,end:endOfDay(e)})}},{id:"this-week",label:t("이번 주"),getRange:({today:t,startOfWeek:e,minDate:n,maxDate:a})=>{const r=((t,e)=>{const n=t.getDay();return addDays(t,-("monday"===e?(n+6)%7:n))})(t,e);return clampRange({start:r,end:(o=r,endOfDay(addDays(o,6)))},n,a);var o}},{id:"this-month",label:t("이번 달"),getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),a.getMonth(),1))),end:getMonthEnd(t)},e,n);var a}},{id:"this-year",label:t("올해"),getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),0,1))),end:getYearEnd(t)},e,n);var a}},{id:"custom",label:t("사용자 지정"),getRange:()=>null}],addMonths=(t,e)=>{const n=new Date(t);return n.setDate(1),n.setMonth(n.getMonth()+e),n},toISODate=t=>`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,parseISODate=t=>{if(!t)return null;const e=t.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const n=new Date(Number(e[1]),Number(e[2])-1,Number(e[3]));return Number.isNaN(n.getTime())?null:startOfDay(n)},formatDisplayDate=(t,n=("ko"===e()?"ko-KR":"en-US"))=>t.toLocaleDateString(n),generateWeekdays=(t,n=("ko"===e()?"ko-KR":"en-US"))=>{const a=Array.from({length:7},(t,e)=>new Intl.DateTimeFormat(n,{weekday:"short"}).format(new Date(2026,0,4+e)));return"monday"===t&&a.push(a.shift()),a},generateCalendarGrid=(t,e,n=!1)=>{const a=t.getFullYear(),r=t.getMonth(),o=new Date(a,r,1),s="monday"===e?(o.getDay()+6)%7:o.getDay();if(n){const t=[];for(let e=0;e<s;e+=1)t.push(null);const e=new Date(a,r+1,0).getDate();for(let n=1;n<=e;n+=1)t.push(new Date(a,r,n));return t}const u=new Date(o);return u.setDate(u.getDate()-s),Array.from({length:42},(t,e)=>{const n=new Date(u);return n.setDate(u.getDate()+e),n})},detectActivePresetId=(t,e,n)=>{if(!t)return"custom";const a=t.start.toDateString(),r=t.end.toDateString();for(const t of e){if("custom"===t.id)continue;const e=t.getRange(n);if(e&&(e.start.toDateString()===a&&e.end.toDateString()===r))return t.id}return"custom"},formatPanelInputDate=(t,e)=>t?t.toLocaleDateString(e,{year:"numeric",month:"short",day:"numeric"}):"";export{n as DEFAULT_DATE_PICKER_PRESETS,addMonths,detectActivePresetId,endOfDay,formatDisplayDate,formatPanelInputDate,generateCalendarGrid,generateWeekdays,parseISODate,startOfDay,toISODate};
|
|
1
|
+
import{dbText as t,getDbLocale as e}from"../core/i18n.js";const startOfDay=t=>{const e=new Date(t);return e.setHours(0,0,0,0),e},endOfDay=t=>{const e=new Date(t);return e.setHours(23,59,59,999),e},addDays=(t,e)=>{const n=new Date(t);return n.setDate(n.getDate()+e),startOfDay(n)},getMonthEnd=t=>endOfDay(new Date(t.getFullYear(),t.getMonth()+1,0)),getYearEnd=t=>endOfDay(new Date(t.getFullYear(),11,31)),clampRange=(t,e,n)=>{let{start:a,end:r}=t;return e&&a<e&&(a=startOfDay(e)),n&&r>n&&(r=endOfDay(n)),a>r?{start:r,end:a}:{start:a,end:r}},n=[{id:"today",label:t("오늘"),getRange:({today:t})=>clampRange({start:startOfDay(t),end:endOfDay(t)})},{id:"yesterday",label:t("어제"),getRange:({today:t})=>{const e=addDays(t,-1);return clampRange({start:e,end:endOfDay(e)})}},{id:"this-week",label:t("이번 주"),getRange:({today:t,startOfWeek:e,minDate:n,maxDate:a})=>{const r=((t,e)=>{const n=t.getDay();return addDays(t,-("monday"===e?(n+6)%7:n))})(t,e);return clampRange({start:r,end:(o=r,endOfDay(addDays(o,6)))},n,a);var o}},{id:"this-month",label:t("이번 달"),getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),a.getMonth(),1))),end:getMonthEnd(t)},e,n);var a}},{id:"this-year",label:t("올해"),getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),0,1))),end:getYearEnd(t)},e,n);var a}},{id:"custom",label:t("사용자 지정"),getRange:()=>null}],addMonths=(t,e)=>{const n=new Date(t);return n.setDate(1),n.setMonth(n.getMonth()+e),n},toISODate=t=>`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,parseISODate=t=>{if(!t)return null;const e=t.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const n=new Date(Number(e[1]),Number(e[2])-1,Number(e[3]));return Number.isNaN(n.getTime())?null:startOfDay(n)},formatDisplayDate=(t,n=("ko"===e()?"ko-KR":"en-US"))=>t.toLocaleDateString(n),generateWeekdays=(t,n=("ko"===e()?"ko-KR":"en-US"))=>{const a=Array.from({length:7},(t,e)=>new Intl.DateTimeFormat(n,{weekday:"short"}).format(new Date(2026,0,4+e)));return"monday"===t&&a.push(a.shift()),a},generateCalendarGrid=(t,e,n=!1)=>{const a=t.getFullYear(),r=t.getMonth(),o=new Date(a,r,1),s="monday"===e?(o.getDay()+6)%7:o.getDay();if(n){const t=[];for(let e=0;e<s;e+=1)t.push(null);const e=new Date(a,r+1,0).getDate();for(let n=1;n<=e;n+=1)t.push(new Date(a,r,n));return t}const u=new Date(o);return u.setDate(u.getDate()-s),Array.from({length:42},(t,e)=>{const n=new Date(u);return n.setDate(u.getDate()+e),n})},detectActivePresetId=(t,e,n)=>{if(!t)return"custom";const a=t.start.toDateString(),r=t.end.toDateString();for(const t of e){if("custom"===t.id)continue;const e=t.getRange(n);if(e&&(e.start.toDateString()===a&&e.end.toDateString()===r))return t.id}return"custom"},formatPanelInputDate=(t,e)=>t?t.toLocaleDateString(e,{year:"numeric",month:"short",day:"numeric"}):"";function resolveDateLocale(t){const n="ko"===e()?"ko-KR":"en-US";if(!t?.trim())return n;try{return Intl.getCanonicalLocales(t)[0]||n}catch{return n}}export{n as DEFAULT_DATE_PICKER_PRESETS,addMonths,detectActivePresetId,endOfDay,formatDisplayDate,formatPanelInputDate,generateCalendarGrid,generateWeekdays,parseISODate,resolveDateLocale,startOfDay,toISODate};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{getDbLocale as e,dbText as t}from"../core/i18n.js";import{sanitizeHref as a}from"../core/safe-url.js";import{ACTIVITY_HEATMAP_SIZES as s,ACTIVITY_HEATMAP_COLOR_SCHEMES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-activity-heatmap";class DbActivityHeatmap extends HTMLElement{constructor(){super(...arguments),this.handleClick=e=>{const t=e.target,a=t?.closest(`.${r}__cell`);if(!a||a.disabled)return;const s=a.dataset.date;if(!s)return;const n=Number(a.dataset.value??"0"),l=Number(a.dataset.level??"0");this.dispatchEvent(new CustomEvent("db-cell-click",{detail:{date:s,value:n,level:l},bubbles:!0,composed:!0}))}}static get observedAttributes(){return["data","end-date","weeks","week-starts-on","size","locale","color-scheme","show-legend","show-month-labels","show-day-labels","legend-less-label","legend-more-label","value-label","max-value","footer-text","footer-href"]}connectedCallback(){this.addEventListener("click",this.handleClick),this.render()}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}attributeChangedCallback(){this.render()}parseData(){const e=this.getAttribute("data");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(e=>e&&"string"==typeof e.date&&"number"==typeof e.value):[]}catch{return[]}}parseEndDate(){const e=this.getAttribute("end-date");if(e){const t=this.parseISODate(e);if(t)return t}const t=new Date;return new Date(t.getFullYear(),t.getMonth(),t.getDate())}parseISODate(e){const t=/^(\d{4})-(\d{2})-(\d{2})/.exec(e.trim());if(!t)return null;const a=Number(t[1]),s=Number(t[2]),n=Number(t[3]);return a&&s&&n?new Date(a,s-1,n):null}formatISODate(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}addDays(e,t){const a=new Date(e);return a.setDate(a.getDate()+t),a}startOfWeek(e,t){const a=(e.getDay()-t+7)%7;return this.addDays(e,-a)}isAfter(e,t){return e.getTime()>t.getTime()}buildWeeks(e,t,a){const s=this.startOfWeek(e,a),n=this.addDays(s,7*-(t-1)),r=[];for(let e=0;e<t;e+=1){const t=[];for(let a=0;a<7;a+=1)t.push(this.addDays(n,7*e+a));r.push(t)}return r}resolveLevel(e,t,a){if(e<=0||t<=0)return 0;const s=e/t;return Math.min(a,Math.max(1,Math.ceil(s*a)))}formatMonthLabel(e,t){return new Intl.DateTimeFormat(t,{month:"short"}).format(e)}formatTooltip(e,t,a,s){const n=new Intl.DateTimeFormat(a,{year:"numeric",month:"long",day:"numeric"}).format(e);return t<=0?`${n}: 활동 없음`:`${n}: ${t.toLocaleString(a)}${s}`}getDayLabels(e,t){const a=Array.from({length:7},(a,s)=>{const n=new Date(2024,0,7+(e+s)%7);return new Intl.DateTimeFormat(t,{weekday:"short"}).format(n)}),s=1===e?[0,2,4,6]:[1,3,5,0];return a.map((e,t)=>s.includes(t)?e:"")}getMonthLabels(e,t){const a=e.map(e=>{const t=e.find(e=>e.getDate()<=7)??e[0];return t.getMonth()+12*t.getFullYear()}),s=e.map(()=>"");let n=0;for(;n<e.length;){const r=a[n];let l=n+1;for(;l<e.length&&a[l]===r;)l+=1;if(l-n>=2){const a=e[n],r=a.find(e=>e.getDate()<=7)??a[0];s[n]=this.formatMonthLabel(r,t)}n=l}return s}render(){const l=this.parseData(),o=new Map(l.map(e=>[e.date,e.value])),i=this.parseEndDate(),c=Math.max(1,Number(this.getAttribute("weeks")??"53")||53),d="0"===this.getAttribute("week-starts-on")?0:1,m=this.getAttribute("size")||"m",u=s.includes(m)?m:"m",h=this.getAttribute("locale")||("ko"===e()?"ko-KR":"en-US"),p=this.getAttribute("color-scheme")||"green",b=n.includes(p)?p:"green",g="false"!==this.getAttribute("show-legend"),f="false"!==this.getAttribute("show-month-labels"),_="false"!==this.getAttribute("show-day-labels"),v=this.getAttribute("legend-less-label")||"적음",$=this.getAttribute("legend-more-label")||"많음",E=this.getAttribute("value-label")||"회",A=this.getAttribute("footer-text")||"",D=this.getAttribute("footer-href")||"",y=this.getAttribute("max-value"),N=l.map(e=>e.value).filter(e=>e>0),k=N.length?Math.max(...N):0,w=y?Math.max(Number(y)||0,k):k,x=this.buildWeeks(i,c,d),C=this.getMonthLabels(x,h),M=this.getDayLabels(d,h);this.className=[r,`${r}--size-${u}`,`${r}--color-${b}`,g&&`${r}--with-legend`].filter(Boolean).join(" "),this.replaceChildren();const L=document.createElement("div");L.className=`${r}__viewport`;const S=document.createElement("div");if(S.className=`${r}__scroll-inner`,_){const e=document.createElement("div");e.className=`${r}__sticky-rail`;const t=document.createElement("div");t.className=`${r}__sticky-spacer`,f||t.classList.add(`${r}__sticky-spacer--hidden`);const a=document.createElement("div");a.className=`${r}__days`,a.setAttribute("aria-hidden","true"),M.forEach(e=>{const t=document.createElement("span");t.className=`${r}__day`,t.textContent=e,a.append(t)}),e.append(t,a),S.append(e)}const T=document.createElement("div");if(T.className=`${r}__grid-area`,f){const e=document.createElement("div");e.className=`${r}__months`,e.setAttribute("aria-hidden","true"),C.forEach(t=>{const a=document.createElement("span");a.className=`${r}__month`,a.textContent=t,e.append(a)}),T.append(e)}const I=document.createElement("div");if(I.className=`${r}__weeks`,I.setAttribute("role","grid"),I.setAttribute("aria-label",t("활동 히트맵")),x.forEach(e=>{const t=document.createElement("div");t.className=`${r}__week`,t.setAttribute("role","row"),e.forEach(e=>{const a=this.formatISODate(e),s=this.isAfter(e,i),n=s?0:o.get(a)??0,l=s?0:this.resolveLevel(n,w,4),c=document.createElement("button");c.type="button",c.className=[`${r}__cell`,`${r}__cell--level-${l}`,s&&`${r}__cell--future`].filter(Boolean).join(" "),c.dataset.date=a,c.dataset.value=String(n),c.dataset.level=String(l),c.title=this.formatTooltip(e,n,h,E),c.setAttribute("aria-label",this.formatTooltip(e,n,h,E)),c.disabled=s,t.append(c)}),I.append(t)}),T.append(I),S.append(T),L.append(S),this.append(L),g||A){const e=document.createElement("div");if(e.className=`${r}__footer`,A)if(D){const t=document.createElement("a");t.className=`${r}__footer-link`,t.href=a(D,"#"),t.textContent=A,e.append(t)}else{const t=document.createElement("span");t.className=`${r}__footer-text`,t.textContent=A,e.append(t)}else e.append(document.createElement("span"));if(g){const t=document.createElement("div");t.className=`${r}__legend`,t.setAttribute("aria-hidden","true");const a=document.createElement("span");a.className=`${r}__legend-label`,a.textContent=v;const s=document.createElement("div");s.className=`${r}__legend-scale`;for(let e=0;e<=4;e+=1){const t=document.createElement("span");t.className=`${r}__legend-cell ${r}__legend-cell--level-${e}`,s.append(t)}const n=document.createElement("span");n.className=`${r}__legend-label`,n.textContent=$,t.append(a,s,n),e.append(t)}this.append(e)}}}customElements.get("db-activity-heatmap")||customElements.define("db-activity-heatmap",DbActivityHeatmap);export{DbActivityHeatmap};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as
|
|
1
|
+
import{setHostClasses as t}from"../core/host-class.js";import{createDbIcon as e,isDbIconName as s}from"./db-icons.js";class DbAiChatList extends HTMLElement{constructor(){super(...arguments),this._items=[]}static get observedAttributes(){return["selected-id","new-label","title-label"]}get items(){return this._items}set items(t){this._items=Array.isArray(t)?t:[],this.render()}get selectedId(){return this.getAttribute("selected-id")||""}set selectedId(t){t?this.setAttribute("selected-id",t):this.removeAttribute("selected-id")}connectedCallback(){if(!this._items.length&&this.hasAttribute("items"))try{this._items=JSON.parse(this.getAttribute("items")||"[]")}catch{this._items=[]}this.render()}attributeChangedCallback(){this.render()}render(){t(this,["designbase-wc-ai-chat-list"]),this.replaceChildren();const i=document.createElement("button");i.type="button",i.className="designbase-wc-ai-chat-list__new";const n=document.createElement("span");n.className="designbase-wc-ai-chat-list__new-icon",n.append(e("plus",18));const a=document.createElement("span");if(a.textContent=this.getAttribute("new-label")||"새 대화",i.append(n,a),i.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-new",{bubbles:!0,composed:!0}))}),this.append(i),!this._items.length)return;const c=new Map,d=this.getAttribute("title-label")||"최근 항목";for(const t of this._items){const e=t.group||d;c.has(e)||c.set(e,[]),c.get(e).push(t)}const l=this.selectedId,o=document.createElement("div");o.className="designbase-wc-ai-chat-list__scroll";for(const[t,i]of c){const n=document.createElement("div");n.className="designbase-wc-ai-chat-list__group";const a=document.createElement("div");a.className="designbase-wc-ai-chat-list__group-title",a.textContent=t,n.append(a);for(const t of i){const i=document.createElement("button");if(i.type="button",i.className=["designbase-wc-ai-chat-list__item",t.id===l&&"designbase-wc-ai-chat-list__item--selected"].filter(Boolean).join(" "),t.icon&&s(t.icon)){const s=document.createElement("span");s.className="designbase-wc-ai-chat-list__item-icon",s.append(e(t.icon,16)),i.append(s)}const a=document.createElement("span");a.className="designbase-wc-ai-chat-list__item-title",a.textContent=t.title,i.append(a),i.addEventListener("click",()=>{this.selectedId=t.id,this.dispatchEvent(new CustomEvent("db-select",{detail:{id:t.id,title:t.title},bubbles:!0,composed:!0}))}),n.append(i)}o.append(n)}this.append(o)}}customElements.get("db-ai-chat-list")||customElements.define("db-ai-chat-list",DbAiChatList);export{DbAiChatList};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"../core/i18n.js";import{DbAiDataElement as
|
|
1
|
+
import{t as e}from"../core/i18n.js";import{DbAiDataElement as t,aiNode as i}from"../core/ai-element.js";class DbAiFileTree extends t{static get observedAttributes(){return["label","items","disabled","selected-id"]}view(){const build=(t,r=[])=>{const s=i("ul","designbase-wc-ai__files","");for(const e of t){const t=document.createElement("li");if(e.children){const i=this.disclosure(`folder:${[...r,e.id].map(encodeURIComponent).join("/")}`,e.label,"complete",[build(e.children,[...r,e.id])],!0,"folder"),s=i.querySelector(".designbase-wc-ai__icon");s?.removeAttribute("aria-label"),s?.setAttribute("aria-hidden","true");const l=i.querySelector("summary"),n=l.lastElementChild;n.classList.add("designbase-wc-ai__folder-chevron"),l.prepend(n),t.append(i)}else{const i=this.button("file-open",e.label,"file-new",e.id);e.id===this.getAttribute("selected-id")&&(i.setAttribute("variant","secondary"),i.setAttribute("aria-current","true")),t.append(i)}s.append(t)}return t.length||s.append(i("li","designbase-wc-ai__empty-folder",e("aiElement.emptyFolder"))),s};if(!this.rows.length)return[i("p","designbase-wc-ai__description",e("aiElement.noFiles"))];const t=i("div","designbase-wc-ai__file-tree","");return t.setAttribute("aria-label",this.attr("label","files")),t.append(build(this.rows)),[t]}}customElements.get("db-ai-file-tree")||customElements.define("db-ai-file-tree",DbAiFileTree);export{DbAiFileTree};
|
|
@@ -8,8 +8,20 @@ interface DbAlertAction {
|
|
|
8
8
|
}
|
|
9
9
|
declare class DbAlert extends HTMLElement {
|
|
10
10
|
static get observedAttributes(): string[];
|
|
11
|
+
/** 소비자가 넣은 자식(링크·코드 등)을 담아 두는 내부 컨테이너. 렌더 사이에 유지된다. */
|
|
12
|
+
private slotEl?;
|
|
13
|
+
private observer?;
|
|
14
|
+
/** 슬롯 내부 변경(React 가 래퍼 안 자식을 바꿀 때)을 감지해 빈 슬롯 여부를 다시 계산한다 */
|
|
15
|
+
private slotObserver?;
|
|
16
|
+
private renderedSlotted;
|
|
11
17
|
connectedCallback(): void;
|
|
18
|
+
disconnectedCallback(): void;
|
|
12
19
|
attributeChangedCallback(): void;
|
|
20
|
+
private getSlot;
|
|
21
|
+
/** 호스트에 직접 붙은 소비자 노드를 슬롯으로 옮긴다. 공백 텍스트는 버린다. */
|
|
22
|
+
private moveChildrenToSlot;
|
|
23
|
+
private adoptChildren;
|
|
24
|
+
private hasSlotted;
|
|
13
25
|
private getIconName;
|
|
14
26
|
private parseActionButtons;
|
|
15
27
|
private render;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as t}from"../core/i18n.js";import"./db-button.js";import{createDbIcon as
|
|
1
|
+
import{dbText as t}from"../core/i18n.js";import{setHostClasses as e}from"../core/host-class.js";import"./db-button.js";import{createDbIcon as s}from"./db-icons.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{ALERT_VARIANTS as n,ALERT_SIZES as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-alert";class DbAlert extends HTMLElement{constructor(){super(...arguments),this.renderedSlotted=!1}static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render(),this.observer??(this.observer=new MutationObserver(()=>this.adoptChildren())),this.observer.observe(this,{childList:!0}),this.slotObserver??(this.slotObserver=new MutationObserver(()=>{this.hasSlotted()!==this.renderedSlotted&&this.render()})),this.slotObserver.observe(this.getSlot(),{childList:!0,subtree:!0,characterData:!0})}disconnectedCallback(){this.observer?.disconnect(),this.slotObserver?.disconnect()}attributeChangedCallback(){this.isConnected&&this.render()}getSlot(){return this.slotEl||(this.slotEl=document.createElement("div"),this.slotEl.className=`${r}__slot`,this.slotEl.setAttribute("data-wc-internal","")),this.slotEl}moveChildrenToSlot(){const t=this.getSlot();let e=!1;for(const s of Array.from(this.childNodes))s instanceof Element&&s.hasAttribute("data-wc-internal")||s.nodeType!==Node.COMMENT_NODE&&(s.nodeType!==Node.TEXT_NODE||s.textContent?.trim()?(t.append(s),e=!0):s.remove());return e}adoptChildren(){this.moveChildrenToSlot()&&this.render()}hasSlotted(){const hasContent=t=>t.nodeType===Node.TEXT_NODE?Boolean(t.textContent?.trim()):t instanceof Element&&(!t.hasAttribute("data-db-children")||Array.from(t.childNodes).some(hasContent));return Boolean(this.slotEl&&Array.from(this.slotEl.childNodes).some(hasContent))}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const a=i(this.getAttribute("variant"),n,"default"),l=i(this.getAttribute("size"),o,"m"),c="false"!==this.getAttribute("show-icon"),d=this.hasAttribute("closable")&&"false"!==this.getAttribute("closable"),h=this.getAttribute("title")?.trim()||"",b=this.getAttribute("message")?.trim()||"",m=this.getAttribute("action-label"),u=this.getAttribute("action-variant")||"tertiary",p=this.parseActionButtons(),v=Boolean(b),E=Boolean(h);this.moveChildrenToSlot();const A=this.hasSlotted();this.renderedSlotted=A;const g=1===Number(E)+Number(v)+Number(A),f=p.length>0?p:m?[{label:m,variant:u}]:[];e(this,[r,`${r}--${a}`,`${r}--${l}`,c&&`${r}--with-icon`,d&&`${r}--closable`,g&&`${r}--text-single`,f.length>0&&`${r}--has-actions`]),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite");const N=this.getSlot(),_=document.createElement("div");if(_.className=`${r}__content`,_.setAttribute("data-wc-internal",""),c){const t=document.createElement("div");t.className=`${r}__icon`,t.append(s(this.getIconName(a),"s"===l?16:"l"===l?24:20)),_.append(t)}const C=document.createElement("div");if(C.className=`${r}__body`,E){const t=document.createElement("div");t.className=`${r}__title`,t.textContent=h,C.append(t)}if(v){const t=document.createElement("div");t.className=`${r}__message`,t.textContent=b,C.append(t)}if(A?C.append(N):N.remove(),_.append(C),f.length>0){const t=document.createElement("div");t.className=`${r}__actions`,t.setAttribute("data-wc-internal","");const e=document.createElement("div");e.className=`${r}__action-buttons`,f.forEach((t,s)=>{const i=document.createElement("db-button");i.setAttribute("variant",t.variant||"tertiary"),i.setAttribute("size",t.size||l),i.textContent=t.label,t.disabled&&i.setAttribute("disabled",""),i.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:s,label:t.label}}))}),e.append(i)}),t.append(e),_.append(t)}if(d){const e=document.createElement("button");e.type="button",e.className=`${r}__close`,e.setAttribute("aria-label",t("알림 닫기")),e.append(s("close",20)),e.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),_.append(e)}this.observer?.disconnect(),this.replaceChildren(_),this.isConnected&&this.observer?.observe(this,{childList:!0})}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{lockScroll as
|
|
1
|
+
import{inheritThemeScope as t}from"../core/theme-scope.js";import{lockScroll as e,unlockScroll as s}from"../core/scroll-lock.js";const i=["fade","slide","zoom","none"];class DbBackdrop extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.keyHandler=null,this.handlePortalClick=t=>{t.target===this.portal&&"true"!==this.getAttribute("disable-backdrop-click")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))}}static get observedAttributes(){return["open","blur","opacity","blur-amount","animation","animation-duration","z-index","background-color","disable-backdrop-click","disable-escape-key-down"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}connectedCallback(){this.style.display="contents",this.syncOpenState()}disconnectedCallback(){this.detachListeners(),this.portal?.remove(),this.portal=void 0,this.releaseScrollLock()}attributeChangedCallback(){this.isConnected&&this.syncOpenState()}isOpen(){return this.open}syncOpenState(){this.isOpen()?this.render():(this.releaseScrollLock(),this.detachListeners(),this.portal?.remove())}collectChildren(){return Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"))}attachListeners(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))},document.addEventListener("keydown",this.keyHandler))}detachListeners(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}render(){if(!this.isOpen())return void this.syncOpenState();const s=this.hasAttribute("blur"),r=this.getAttribute("opacity")||"0.5",o=this.getAttribute("blur-amount")||"4",a=i.includes(this.getAttribute("animation")||"fade")&&this.getAttribute("animation")||"fade",n=this.getAttribute("animation-duration")||"300",l=this.getAttribute("z-index")||"1000",c=this.getAttribute("background-color"),d=this.collectChildren();this.scrollLocked||(e(),this.scrollLocked=!0),this.attachListeners(),this.portal||(this.portal=document.createElement("div"),this.portal.setAttribute("data-wc-internal",""),this.portal.addEventListener("click",this.handlePortalClick)),this.portal.className=["designbase-wc-backdrop",`designbase-wc-backdrop--${a}`,"designbase-wc-backdrop--open",s?"designbase-wc-backdrop--blur":""].filter(Boolean).join(" "),this.portal.setAttribute("role","presentation"),this.portal.setAttribute("aria-hidden","false"),this.portal.style.setProperty("--backdrop-opacity",r),this.portal.style.setProperty("--backdrop-blur-amount",`${o}px`),this.portal.style.setProperty("--backdrop-animation-duration",`${n}ms`),this.portal.style.setProperty("--backdrop-z-index",l),c?this.portal.style.backgroundColor=c:this.portal.style.removeProperty("background-color"),this.portal.replaceChildren(...d),this.portal.isConnected||(t(this,this.portal),document.body.append(this.portal))}releaseScrollLock(){this.scrollLocked&&(this.scrollLocked=!1,s())}}customElements.get("db-backdrop")||customElements.define("db-backdrop",DbBackdrop);export{DbBackdrop};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as t}from"../core/i18n.js";import{createDbIcon as e}from"./db-icons.js";import{createFocusTrap as s}from"../core/focus-trap.js";import{unlockScroll as i,lockScroll as r}from"../core/scroll-lock.js";import{BOTTOM_SHEET_VARIANTS as o,BOTTOM_SHEET_ANIMATIONS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={s:40,m:60,l:80,full:100};function resolveHeightPercent(t){if(!t)return a.m;const e=a[t];if(e)return Math.min(100,Math.max(20,e));const s=Number(t);return Number.isFinite(s)?Math.min(100,Math.max(20,s)):a.m}class DbBottomSheet extends HTMLElement{constructor(){super(...arguments),this.sheetHeightPercent=a.m,this.scrollLocked=!1,this.isDragging=!1,this.isVisible=!1,this.isMounted=!1,this.keyHandler=null,this.dragState={active:!1,pointerId:-1,startY:0,startHeight:a.m,lastY:0,lastTime:0},this.handlePointerDown=t=>{"true"!==this.getAttribute("disable-drag")&&0===t.button&&(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),this.dragState={active:!0,pointerId:t.pointerId,startY:t.clientY,startHeight:this.sheetHeightPercent,lastY:t.clientY,lastTime:Date.now()},this.isDragging=!0,this.syncActiveClasses())},this.handlePointerMove=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;t.preventDefault(),e.lastY=t.clientY,e.lastTime=Date.now();const s=window.innerHeight||1,i=(e.startY-t.clientY)/s*100,r=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheetHeightPercent=Math.min(r,Math.max(20,e.startHeight+i)),this.applySheetDimensions()},this.handlePointerUp=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;const s=t.currentTarget;s.hasPointerCapture(t.pointerId)&&s.releasePointerCapture(t.pointerId),this.finishDrag()}}static get observedAttributes(){return["open","title","subtitle","height","max-height","variant","disable-backdrop-click","disable-escape-key-down","disable-drag","show-close-button","animation","animation-duration","z-index","show-backdrop","backdrop-blur","backdrop-opacity","sticky-header","sticky-footer"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}shouldMountPortal(){return this.isOpenRequested()||this.isMounted}connectedCallback(){this.style.display="contents",this.childObserver=new MutationObserver(()=>{this.isOpenRequested()&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),this.childObserver=void 0,this.clearTimers(),this.detachEscape(),this.root?.remove(),this.root=void 0,this.teardownOverlay()}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,i())}attributeChangedCallback(t){this.isConnected&&("open"!==t?("height"===t&&this.isOpenRequested()&&(this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height"))),this.shouldMountPortal()&&(this.render(),this.isMounted&&this.syncActiveClasses())):this.syncOpenState())}isOpenRequested(){return this.open}clearTimers(){this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}scheduleEnterAnimation(){this.enterFrame&&cancelAnimationFrame(this.enterFrame),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isOpenRequested()&&this.sheet&&(this.sheet.offsetHeight,this.isVisible=!0,this.syncActiveClasses())})})}getMaxHeightLimit(t){const e=Number(this.getAttribute("max-height")||0),s=t>=100;return Math.min(100,Math.max(t,e||(s?100:90)))}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}collectSlotted(t){const e=Array.from(this.querySelectorAll(`:scope > [slot="${t}"]`));if(e.length)return e;if("header"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");return t?Array.from(t.children):[]}if("footer"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");return t?Array.from(t.children):[]}return[]}collectContentNodes(){const t=Array.from(this.children).filter(t=>{const e=t.getAttribute("slot");return!e||"default"===e});return t.length?t:this.contentEl?Array.from(this.contentEl.children):[]}finishDrag(){const t=this.dragState;if(!t.active)return;t.active=!1,this.isDragging=!1;const e=t.lastY-t.startY,s=e/Math.max(1,Date.now()-t.lastTime),i=window.innerHeight||1,r=(t.startY-t.lastY)/i*100,o=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height"))),n=Math.min(o,Math.max(20,t.startHeight+r));n<=22||e>72||s>.6?this.close():(this.sheetHeightPercent=n,this.applySheetDimensions(),this.syncActiveClasses())}syncOpenState(){const t=this.isOpenRequested(),e=Number(this.getAttribute("animation-duration")||400);if(this.clearTimers(),t)return this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height")),this.render(),this.isMounted=!0,this.isVisible=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&document.body.append(this.root),this.scheduleEnterAnimation(),this.scrollLocked||(r(),this.scrollLocked=!0),this.sheet&&!this.focusTrap&&(this.focusTrap=s(this.sheet),requestAnimationFrame(()=>this.focusTrap?.activate())),void this.attachEscape();this.isVisible=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.detachContentToHost(),this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.teardownOverlay(),this.detachEscape()},e),this.detachEscape()}syncActiveClasses(){if(!this.sheet)return;const t=resolveHeightPercent(this.getAttribute("height")),e=this.getAttribute("variant")||"default",s=this.getAttribute("animation")||"slide",i=o.includes(e)?e:"default",r=n.includes(s)?s:"slide",a="false"!==this.getAttribute("show-backdrop"),h=this.hasAttribute("sticky-header"),c=this.hasAttribute("sticky-footer");this.sheet.className=["designbase-wc-bottom-sheet",`designbase-wc-bottom-sheet--${i}`,`designbase-wc-bottom-sheet--${r}`,this.isMounted&&this.isVisible&&"designbase-wc-bottom-sheet--open",this.isDragging&&"designbase-wc-bottom-sheet--dragging",h&&"designbase-wc-bottom-sheet--sticky-header",c&&"designbase-wc-bottom-sheet--sticky-footer",!a&&"designbase-wc-bottom-sheet--no-backdrop",(t>=100||this.sheetHeightPercent>=100)&&"designbase-wc-bottom-sheet--full"].filter(Boolean).join(" "),this.backdrop?.classList.toggle("designbase-wc-backdrop--open",this.isMounted&&this.isVisible)}applySheetDimensions(){if(!this.sheet)return;const t=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheet.style.height=`${this.sheetHeightPercent}vh`,this.sheet.style.maxHeight=`${t}vh`}detachContentToHost(){this.contentEl&&Array.from(this.contentEl.children).forEach(t=>this.append(t));const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");t&&Array.from(t.children).forEach(t=>{"bottom-sheet-title"!==t.id&&"bottom-sheet-subtitle"!==t.id&&this.append(t)});const e=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");e&&Array.from(e.children).forEach(t=>this.append(t))}render(){if(!this.shouldMountPortal())return;const s=this.getAttribute("title"),i=this.getAttribute("subtitle"),r="false"!==this.getAttribute("show-close-button"),o="false"!==this.getAttribute("show-backdrop"),n=this.hasAttribute("backdrop-blur"),a=this.getAttribute("backdrop-opacity")||"0.5",h=this.getAttribute("animation-duration")||"400",c=this.getAttribute("z-index")||"1000",d=this.hasAttribute("sticky-header"),l=this.hasAttribute("sticky-footer"),b=this.collectSlotted("header"),m=this.collectSlotted("footer"),u=this.collectContentNodes();if(this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.backdrop=document.createElement("div"),this.backdrop.className="designbase-wc-backdrop designbase-wc-backdrop--bottom-sheet",this.backdrop.setAttribute("role","presentation"),this.backdrop.addEventListener("click",t=>{t.target===this.backdrop&&"true"!==this.getAttribute("disable-backdrop-click")&&this.close()}),this.sheet=document.createElement("div"),this.sheet.setAttribute("role","dialog"),this.sheet.setAttribute("aria-modal","true"),this.grabBar=document.createElement("div"),this.grabBar.className="designbase-wc-bottom-sheet__grab-bar",this.grabBar.addEventListener("pointerdown",this.handlePointerDown),this.grabBar.addEventListener("pointermove",this.handlePointerMove),this.grabBar.addEventListener("pointerup",this.handlePointerUp),this.grabBar.addEventListener("pointercancel",this.handlePointerUp),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-bottom-sheet__content"),this.root.replaceChildren(),o&&this.backdrop&&(this.backdrop.className=["designbase-wc-backdrop","designbase-wc-backdrop--bottom-sheet",n&&"designbase-wc-backdrop--blur"].filter(Boolean).join(" "),this.backdrop.style.setProperty("--backdrop-opacity",a),this.backdrop.style.setProperty("--bottom-sheet-animation-duration",`${h}ms`),this.backdrop.style.zIndex=c,this.backdrop.setAttribute("aria-hidden",String(!this.isOpenRequested())),this.root.append(this.backdrop)),!this.sheet||!this.grabBar||!this.contentEl)return;this.sheet.style.zIndex=String(Number(c)+1),this.sheet.style.setProperty("--bottom-sheet-animation-duration",`${h}ms`),this.applySheetDimensions(),s?this.sheet.setAttribute("aria-labelledby","bottom-sheet-title"):this.sheet.removeAttribute("aria-labelledby"),i?this.sheet.setAttribute("aria-describedby","bottom-sheet-subtitle"):this.sheet.removeAttribute("aria-describedby"),this.sheet.replaceChildren();const p="true"===this.getAttribute("disable-drag");if(this.grabBar.className=["designbase-wc-bottom-sheet__grab-bar",!p&&"designbase-wc-bottom-sheet__grab-bar--draggable"].filter(Boolean).join(" "),this.grabBar.replaceChildren(),!p){const t=document.createElement("div");t.className="designbase-wc-bottom-sheet__handle",t.setAttribute("aria-hidden","true"),this.grabBar.append(t)}this.sheet.append(this.grabBar);if(Boolean(s||i||b.length||r)){const o=document.createElement("div");o.className=["designbase-wc-bottom-sheet__header",d&&"designbase-wc-bottom-sheet__header--sticky"].filter(Boolean).join(" ");const n=document.createElement("div");if(n.className="designbase-wc-bottom-sheet__header-main",b.length)b.forEach(t=>n.append(t));else{if(s){const t=document.createElement("h2");t.id="bottom-sheet-title",t.className="designbase-wc-bottom-sheet__title",t.textContent=s,n.append(t)}if(i){const t=document.createElement("p");t.id="bottom-sheet-subtitle",t.className="designbase-wc-bottom-sheet__subtitle",t.textContent=i,n.append(t)}}if(o.append(n),r){const s=document.createElement("button");s.type="button",s.className="designbase-wc-bottom-sheet__close-button",s.setAttribute("aria-label",t("닫기")),s.append(e("close",20)),s.addEventListener("click",()=>this.close()),o.append(s)}this.sheet.append(o)}if(this.contentEl.replaceChildren(...u),this.sheet.append(this.contentEl),m.length){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__footer",l&&"designbase-wc-bottom-sheet__footer--sticky"].filter(Boolean).join(" "),m.forEach(e=>t.append(e)),this.sheet.append(t)}this.root.append(this.sheet),this.isMounted&&!this.root.isConnected&&document.body.append(this.root),this.syncActiveClasses()}}customElements.get("db-bottom-sheet")||customElements.define("db-bottom-sheet",DbBottomSheet);export{DbBottomSheet};
|
|
1
|
+
import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as e}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{createFocusTrap as i}from"../core/focus-trap.js";import{unlockScroll as r,lockScroll as o}from"../core/scroll-lock.js";import{BOTTOM_SHEET_VARIANTS as n,BOTTOM_SHEET_ANIMATIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={s:40,m:60,l:80,full:100};function resolveHeightPercent(t){if(!t)return a.m;const e=a[t];if(e)return Math.min(100,Math.max(20,e));const s=Number(t);return Number.isFinite(s)?Math.min(100,Math.max(20,s)):a.m}class DbBottomSheet extends HTMLElement{constructor(){super(...arguments),this.sheetHeightPercent=a.m,this.scrollLocked=!1,this.isDragging=!1,this.isVisible=!1,this.isMounted=!1,this.keyHandler=null,this.dragState={active:!1,pointerId:-1,startY:0,startHeight:a.m,lastY:0,lastTime:0},this.handlePointerDown=t=>{"true"!==this.getAttribute("disable-drag")&&0===t.button&&(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),this.dragState={active:!0,pointerId:t.pointerId,startY:t.clientY,startHeight:this.sheetHeightPercent,lastY:t.clientY,lastTime:Date.now()},this.isDragging=!0,this.syncActiveClasses())},this.handlePointerMove=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;t.preventDefault(),e.lastY=t.clientY,e.lastTime=Date.now();const s=window.innerHeight||1,i=(e.startY-t.clientY)/s*100,r=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheetHeightPercent=Math.min(r,Math.max(20,e.startHeight+i)),this.applySheetDimensions()},this.handlePointerUp=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;const s=t.currentTarget;s.hasPointerCapture(t.pointerId)&&s.releasePointerCapture(t.pointerId),this.finishDrag()}}static get observedAttributes(){return["open","title","subtitle","height","max-height","variant","disable-backdrop-click","disable-escape-key-down","disable-drag","show-close-button","animation","animation-duration","z-index","show-backdrop","backdrop-blur","backdrop-opacity","sticky-header","sticky-footer"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}shouldMountPortal(){return this.isOpenRequested()||this.isMounted}connectedCallback(){this.style.display="contents",this.childObserver=new MutationObserver(()=>{this.isOpenRequested()&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),this.childObserver=void 0,this.clearTimers(),this.detachEscape(),this.root?.remove(),this.root=void 0,this.teardownOverlay()}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,r())}attributeChangedCallback(t){this.isConnected&&("open"!==t?("height"===t&&this.isOpenRequested()&&(this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height"))),this.shouldMountPortal()&&(this.render(),this.isMounted&&this.syncActiveClasses())):this.syncOpenState())}isOpenRequested(){return this.open}clearTimers(){this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}scheduleEnterAnimation(){this.enterFrame&&cancelAnimationFrame(this.enterFrame),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isOpenRequested()&&this.sheet&&(this.sheet.offsetHeight,this.isVisible=!0,this.syncActiveClasses())})})}getMaxHeightLimit(t){const e=Number(this.getAttribute("max-height")||0),s=t>=100;return Math.min(100,Math.max(t,e||(s?100:90)))}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}collectSlotted(t){const e=Array.from(this.querySelectorAll(`:scope > [slot="${t}"]`));if(e.length)return e;if("header"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");return t?Array.from(t.children):[]}if("footer"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");return t?Array.from(t.children):[]}return[]}collectContentNodes(){const t=Array.from(this.children).filter(t=>{const e=t.getAttribute("slot");return!e||"default"===e});return t.length?t:this.contentEl?Array.from(this.contentEl.children):[]}finishDrag(){const t=this.dragState;if(!t.active)return;t.active=!1,this.isDragging=!1;const e=t.lastY-t.startY,s=e/Math.max(1,Date.now()-t.lastTime),i=window.innerHeight||1,r=(t.startY-t.lastY)/i*100,o=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height"))),n=Math.min(o,Math.max(20,t.startHeight+r));n<=22||e>72||s>.6?this.close():(this.sheetHeightPercent=n,this.applySheetDimensions(),this.syncActiveClasses())}syncOpenState(){const e=this.isOpenRequested(),s=Number(this.getAttribute("animation-duration")||400);if(this.clearTimers(),e)return this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height")),this.render(),this.isMounted=!0,this.isVisible=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root)),this.scheduleEnterAnimation(),this.scrollLocked||(o(),this.scrollLocked=!0),this.sheet&&!this.focusTrap&&(this.focusTrap=i(this.sheet),requestAnimationFrame(()=>this.focusTrap?.activate())),void this.attachEscape();this.isVisible=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.detachContentToHost(),this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.teardownOverlay(),this.detachEscape()},s),this.detachEscape()}syncActiveClasses(){if(!this.sheet)return;const t=resolveHeightPercent(this.getAttribute("height")),e=this.getAttribute("variant")||"default",s=this.getAttribute("animation")||"slide",i=n.includes(e)?e:"default",r=h.includes(s)?s:"slide",o="false"!==this.getAttribute("show-backdrop"),a=this.hasAttribute("sticky-header"),c=this.hasAttribute("sticky-footer");this.sheet.className=["designbase-wc-bottom-sheet",`designbase-wc-bottom-sheet--${i}`,`designbase-wc-bottom-sheet--${r}`,this.isMounted&&this.isVisible&&"designbase-wc-bottom-sheet--open",this.isDragging&&"designbase-wc-bottom-sheet--dragging",a&&"designbase-wc-bottom-sheet--sticky-header",c&&"designbase-wc-bottom-sheet--sticky-footer",!o&&"designbase-wc-bottom-sheet--no-backdrop",(t>=100||this.sheetHeightPercent>=100)&&"designbase-wc-bottom-sheet--full"].filter(Boolean).join(" "),this.backdrop?.classList.toggle("designbase-wc-backdrop--open",this.isMounted&&this.isVisible)}applySheetDimensions(){if(!this.sheet)return;const t=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheet.style.height=`${this.sheetHeightPercent}vh`,this.sheet.style.maxHeight=`${t}vh`}detachContentToHost(){this.contentEl&&Array.from(this.contentEl.children).forEach(t=>this.append(t));const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");t&&Array.from(t.children).forEach(t=>{"bottom-sheet-title"!==t.id&&"bottom-sheet-subtitle"!==t.id&&this.append(t)});const e=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");e&&Array.from(e.children).forEach(t=>this.append(t))}render(){if(!this.shouldMountPortal())return;const i=this.getAttribute("title"),r=this.getAttribute("subtitle"),o="false"!==this.getAttribute("show-close-button"),n="false"!==this.getAttribute("show-backdrop"),h=this.hasAttribute("backdrop-blur"),a=this.getAttribute("backdrop-opacity")||"0.5",c=this.getAttribute("animation-duration")||"400",d=this.getAttribute("z-index")||"1000",l=this.hasAttribute("sticky-header"),b=this.hasAttribute("sticky-footer"),m=this.collectSlotted("header"),u=this.collectSlotted("footer"),p=this.collectContentNodes();if(this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.backdrop=document.createElement("div"),this.backdrop.className="designbase-wc-backdrop designbase-wc-backdrop--bottom-sheet",this.backdrop.setAttribute("role","presentation"),this.backdrop.addEventListener("click",t=>{t.target===this.backdrop&&"true"!==this.getAttribute("disable-backdrop-click")&&this.close()}),this.sheet=document.createElement("div"),this.sheet.setAttribute("role","dialog"),this.sheet.setAttribute("aria-modal","true"),this.grabBar=document.createElement("div"),this.grabBar.className="designbase-wc-bottom-sheet__grab-bar",this.grabBar.addEventListener("pointerdown",this.handlePointerDown),this.grabBar.addEventListener("pointermove",this.handlePointerMove),this.grabBar.addEventListener("pointerup",this.handlePointerUp),this.grabBar.addEventListener("pointercancel",this.handlePointerUp),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-bottom-sheet__content"),this.root.replaceChildren(),n&&this.backdrop&&(this.backdrop.className=["designbase-wc-backdrop","designbase-wc-backdrop--bottom-sheet",h&&"designbase-wc-backdrop--blur"].filter(Boolean).join(" "),this.backdrop.style.setProperty("--backdrop-opacity",a),this.backdrop.style.setProperty("--bottom-sheet-animation-duration",`${c}ms`),this.backdrop.style.zIndex=d,this.backdrop.setAttribute("aria-hidden",String(!this.isOpenRequested())),this.root.append(this.backdrop)),!this.sheet||!this.grabBar||!this.contentEl)return;this.sheet.style.zIndex=String(Number(d)+1),this.sheet.style.setProperty("--bottom-sheet-animation-duration",`${c}ms`),this.applySheetDimensions(),i?this.sheet.setAttribute("aria-labelledby","bottom-sheet-title"):this.sheet.removeAttribute("aria-labelledby"),r?this.sheet.setAttribute("aria-describedby","bottom-sheet-subtitle"):this.sheet.removeAttribute("aria-describedby"),this.sheet.replaceChildren();const g="true"===this.getAttribute("disable-drag");if(this.grabBar.className=["designbase-wc-bottom-sheet__grab-bar",!g&&"designbase-wc-bottom-sheet__grab-bar--draggable"].filter(Boolean).join(" "),this.grabBar.replaceChildren(),!g){const t=document.createElement("div");t.className="designbase-wc-bottom-sheet__handle",t.setAttribute("aria-hidden","true"),this.grabBar.append(t)}this.sheet.append(this.grabBar);if(Boolean(i||r||m.length||o)){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__header",l&&"designbase-wc-bottom-sheet__header--sticky"].filter(Boolean).join(" ");const n=document.createElement("div");if(n.className="designbase-wc-bottom-sheet__header-main",m.length)m.forEach(t=>n.append(t));else{if(i){const t=document.createElement("h2");t.id="bottom-sheet-title",t.className="designbase-wc-bottom-sheet__title",t.textContent=i,n.append(t)}if(r){const t=document.createElement("p");t.id="bottom-sheet-subtitle",t.className="designbase-wc-bottom-sheet__subtitle",t.textContent=r,n.append(t)}}if(t.append(n),o){const i=document.createElement("button");i.type="button",i.className="designbase-wc-bottom-sheet__close-button",i.setAttribute("aria-label",e("닫기")),i.append(s("close",20)),i.addEventListener("click",()=>this.close()),t.append(i)}this.sheet.append(t)}if(this.contentEl.replaceChildren(...p),this.sheet.append(this.contentEl),u.length){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__footer",b&&"designbase-wc-bottom-sheet__footer--sticky"].filter(Boolean).join(" "),u.forEach(e=>t.append(e)),this.sheet.append(t)}this.root.append(this.sheet),this.isMounted&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root)),this.syncActiveClasses()}}customElements.get("db-bottom-sheet")||customElements.define("db-bottom-sheet",DbBottomSheet);export{DbBottomSheet};
|
|
@@ -36,7 +36,8 @@ declare class DbCalendar extends HTMLElement {
|
|
|
36
36
|
private eventForm;
|
|
37
37
|
connectedCallback(): void;
|
|
38
38
|
attributeChangedCallback(): void;
|
|
39
|
-
|
|
39
|
+
get locale(): string;
|
|
40
|
+
set locale(value: string);
|
|
40
41
|
private get showWeekends();
|
|
41
42
|
private get highlightToday();
|
|
42
43
|
private get showOutsideDays();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as e,getDbLocale as t}from"../core/i18n.js";import{createDbIcon as a,getDbComponentIconSize as n}from"./db-icons.js";import{parseISODate as s,toISODate as i}from"./date-picker-utils.js";import"./db-modal.js";import"./db-input.js";import"./db-select.js";import"./db-date-picker.js";import"./db-time-picker.js";import"./db-button.js";const d="designbase-wc-calendar";class DbCalendar extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.currentView="month",this.selectedDate=new Date,this._events=[],this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.draggedEvent=null,this.dragOverDate=null,this.selectedDateRange={start:null,end:null},this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""}}static get observedAttributes(){return["view","current-date","events","locale","show-weekends","highlight-today","show-outside-days"]}connectedCallback(){this.built||this.build(),this.readAttributes(),this.render()}attributeChangedCallback(){this.built&&(this.readAttributes(),this.render())}get locale(){return this.getAttribute("locale")||("ko"===t()?"ko-KR":"en-US")}get showWeekends(){return"false"!==this.getAttribute("show-weekends")}get highlightToday(){return"false"!==this.getAttribute("highlight-today")}get showOutsideDays(){return"false"!==this.getAttribute("show-outside-days")}get events(){return this._events}set events(e){"string"!=typeof e?(this._events=Array.isArray(e)?e:[],this.setAttribute("events",JSON.stringify(this._events))):this.setAttribute("events",e)}build(){this.built=!0,this.headerEl=document.createElement("div"),this.headerEl.className=`${d}__header`,this.bodyEl=document.createElement("div"),this.bodyEl.className=`${d}__body`,this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","m"),this.modalEl.addEventListener("db-close",()=>this.closeModal())}readAttributes(){this.currentView="month";const e=s(this.getAttribute("current-date"));e&&(this.selectedDate=e);const t=this.getAttribute("events");if(t)try{const e=JSON.parse(t);this._events=Array.isArray(e)?e:[]}catch{this._events=[]}else this._events=[]}isSameDate(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}eventsForDate(e){return this._events.filter(t=>{const a=s(t.date);return!!a&&this.isSameDate(a,e)})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}handleViewChange(e){this.currentView="month",this.emit("db-view-change",{view:e}),this.render()}shiftMonth(e){const t=new Date(this.selectedDate);t.setMonth(t.getMonth()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}shiftYear(e){const t=new Date(this.selectedDate);t.setFullYear(t.getFullYear()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}handleDateClick(e){this.selectedDate=e,this.emit("db-date-click",{date:i(e)}),!this.selectedDateRange.start||this.selectedDateRange.start&&this.selectedDateRange.end?this.selectedDateRange={start:e,end:null}:this.selectedDateRange.start&&!this.selectedDateRange.end&&(e<this.selectedDateRange.start?this.selectedDateRange={start:e,end:this.selectedDateRange.start}:this.selectedDateRange={start:this.selectedDateRange.start,end:e}),this.openAddModal(e)}handleDragStart(e,t){this.draggedEvent=e,t.dataTransfer?.setData("text/plain",e.id),t.dataTransfer?.setData("application/json",JSON.stringify(e)),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")}handleDragOver(e,t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"),this.dragOverDate=e,this.render()}handleDragLeave(e){const t=e.relatedTarget,a=e.currentTarget;a&&t&&a.contains(t)||(this.dragOverDate=null,this.render())}handleDrop(e,t){if(t.preventDefault(),!this.draggedEvent)return;const a={...this.draggedEvent,date:i(e)};this.emit("db-event-edit",{event:a}),this.draggedEvent=null,this.dragOverDate=null,this.render()}handleDragEnd(){this.draggedEvent=null,this.dragOverDate=null,this.render()}handleEventClick(e,t){t.stopPropagation(),this.selectedEvent=e,this.isEditing=!0;const a=s(e.date);a&&(this.selectedDate=a),this.eventForm={title:e.title,description:e.description||"",startTime:e.startTime||"09:00",endTime:e.endTime||"10:00",type:e.type,color:e.color||"#17a2b8",isAllDay:e.isAllDay||!1,location:e.location||""},this.emit("db-event-click",{event:e}),this.showEventModal=!0,this.render()}openAddModal(e){this.selectedDate=e,this.selectedEvent=null,this.isEditing=!1,this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""},this.showEventModal=!0,this.render()}closeModal(){this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.render()}saveEvent(){if(!this.eventForm.title.trim())return void window.alert("제목을 입력해주세요.");const e={title:this.eventForm.title.trim(),description:this.eventForm.description,date:i(this.selectedDate),startTime:this.eventForm.startTime,endTime:this.eventForm.endTime,type:this.eventForm.type,color:this.eventForm.color,isAllDay:this.eventForm.isAllDay,location:this.eventForm.location};if(this.isEditing&&this.selectedEvent){const t={...this.selectedEvent,...e};this.emit("db-event-edit",{event:t})}else this.emit("db-event-add",{event:e});this.closeModal()}deleteEvent(){this.selectedEvent&&window.confirm("정말로 이 일정을 삭제하시겠습니까?")&&(this.emit("db-event-delete",{eventId:this.selectedEvent.id}),this.closeModal())}renderHeader(){if(!this.headerEl)return;this.headerEl.replaceChildren();const t=document.createElement("div");t.className=`${d}__navigation`;const s=n("m"),i=document.createElement("button");i.type="button",i.className=`${d}__nav-button`,i.setAttribute("aria-label",e("이전")),i.appendChild(a("chevron-left",s)),i.addEventListener("click",()=>{this.shiftMonth(-1)});const l=document.createElement("div");l.className=`${d}__title`,l.textContent=this.selectedDate.toLocaleDateString(this.locale,{year:"numeric",month:"long"});const r=document.createElement("button");r.type="button",r.className=`${d}__nav-button`,r.setAttribute("aria-label",e("다음")),r.appendChild(a("chevron-right",s)),r.addEventListener("click",()=>{this.shiftMonth(1)}),t.append(i,l,r),this.headerEl.appendChild(t)}renderMonthView(){const e=document.createElement("div");e.className=`${d}__month-view`;const t=document.createElement("div");t.className=`${d}__weekdays`,["일","월","화","수","목","금","토"].forEach(e=>{const a=document.createElement("div");a.className=`${d}__weekday`,a.textContent=e,t.appendChild(a)}),e.appendChild(t);const a=document.createElement("div");a.className=`${d}__days`;const n=this.selectedDate.getFullYear(),s=this.selectedDate.getMonth(),i=new Date(n,s,1),l=new Date(i);l.setDate(l.getDate()-i.getDay());const r=new Date;for(let e=0;e<42;e+=1){const t=new Date(l);t.setDate(l.getDate()+e);const n=t.getMonth()===s;if(!this.showOutsideDays&&!n)continue;const i=0===t.getDay()||6===t.getDay();if(!this.showWeekends&&i)continue;const o=document.createElement("div"),c=this.selectedDateRange.start&&this.selectedDateRange.end&&t>=this.selectedDateRange.start&&t<=this.selectedDateRange.end,h=this.selectedDateRange.start&&t.toDateString()===this.selectedDateRange.start.toDateString(),m=this.selectedDateRange.end&&t.toDateString()===this.selectedDateRange.end.toDateString(),u=Boolean(c&&!h&&!m);o.className=[`${d}__day`,n&&`${d}__day--current-month`,this.highlightToday&&t.toDateString()===r.toDateString()&&`${d}__day--today`,this.isSameDate(t,this.selectedDate)&&`${d}__day--selected`,h&&`${d}__day--selected--start`,m&&`${d}__day--selected--end`,u&&`${d}__day--selected--middle`,!this.showWeekends&&i&&`${d}__day--weekend`].filter(Boolean).join(" "),o.addEventListener("click",()=>this.handleDateClick(t));const v=document.createElement("span");v.className=`${d}__day-number`,v.textContent=String(t.getDate()),o.appendChild(v);const p=this.eventsForDate(t);if(p.length){const e=document.createElement("div");if(e.className=`${d}__day-events`,p.slice(0,2).forEach(t=>{const a=document.createElement("div");a.className=[`${d}__event-bar`,`${d}__event-bar--${t.type}`].filter(Boolean).join(" "),t.color&&(a.style.backgroundColor=t.color),this.draggedEvent?.id===t.id&&a.classList.add(`${d}__event-bar--dragging`),a.title=t.title,a.draggable=!0;const n=document.createElement("span");n.className=`${d}__event-title`,n.textContent=t.title,a.appendChild(n),a.addEventListener("click",e=>this.handleEventClick(t,e)),a.addEventListener("dragstart",e=>this.handleDragStart(t,e)),a.addEventListener("dragend",()=>this.handleDragEnd()),e.appendChild(a)}),p.length>2){const t=document.createElement("div");t.className=`${d}__more-events`,t.textContent=`+${p.length-2} more`,e.appendChild(t)}o.appendChild(e)}const g=document.createElement("div");g.className=[`${d}__drop-zone`,this.dragOverDate&&this.isSameDate(this.dragOverDate,t)&&`${d}__drop-zone--active`].filter(Boolean).join(" "),g.addEventListener("dragover",e=>this.handleDragOver(t,e)),g.addEventListener("dragleave",e=>this.handleDragLeave(e)),g.addEventListener("drop",e=>this.handleDrop(t,e)),o.appendChild(g),a.appendChild(o)}return e.appendChild(a),e}renderYearView(){const e=document.createElement("div");e.className=`${d}__year-view`;const t=this.selectedDate.getFullYear();for(let a=0;a<12;a+=1){const n=new Date(t,a,1),i=this._events.filter(e=>{const n=s(e.date);return n&&n.getFullYear()===t&&n.getMonth()===a}),l=document.createElement("div");l.className=`${d}__year-month`,l.addEventListener("click",()=>{this.selectedDate=n,this.handleViewChange("month")});const r=document.createElement("h3");if(r.className=`${d}__year-month-title`,r.textContent=n.toLocaleDateString(this.locale,{month:"long"}),l.appendChild(r),i.length){const e=document.createElement("div");if(e.className=`${d}__year-month-events`,i.slice(0,4).forEach(t=>{const a=document.createElement("span");a.className=[`${d}__year-event`,`${d}__year-event--${t.type}`].join(" "),t.color&&(a.style.backgroundColor=t.color),e.appendChild(a)}),i.length>4){const t=document.createElement("span");t.className=`${d}__year-more-events`,t.textContent=`+${i.length-4} more`,e.appendChild(t)}l.appendChild(e)}e.appendChild(l)}return e}renderWeekView(){const e=document.createElement("div");e.className=`${d}__week-view`;const t=new Date,a=new Date(this.selectedDate);a.setDate(this.selectedDate.getDate()-this.selectedDate.getDay());const n=document.createElement("div");n.className=`${d}__week-header`;const s=document.createElement("div");s.className=`${d}__time-column-header`,n.appendChild(s);for(let e=0;e<7;e+=1){const s=new Date(a);s.setDate(a.getDate()+e);const i=document.createElement("div");i.className=[`${d}__week-day-header`,s.toDateString()===t.toDateString()&&`${d}__week-day-header--today`].filter(Boolean).join(" ");const l=document.createElement("span");l.className=`${d}__week-day-name`,l.textContent=s.toLocaleDateString(this.locale,{weekday:"short"});const r=document.createElement("span");r.className=`${d}__week-day-number`,r.textContent=String(s.getDate()),i.append(l,r),n.appendChild(i)}e.appendChild(n);const i=document.createElement("div");i.className=`${d}__week-grid`;const l=document.createElement("div");l.className=`${d}__week-time-column`;for(let e=6;e<=22;e+=1){const t=document.createElement("div");t.className=`${d}__time-slot`;const a=document.createElement("span");a.className=`${d}__time-label`,a.textContent=`${String(e).padStart(2,"0")}:00`,t.appendChild(a),l.appendChild(t)}i.appendChild(l);const r=document.createElement("div");r.className=`${d}__week-columns`;for(let e=0;e<7;e+=1){const t=new Date(a);t.setDate(a.getDate()+e);const n=document.createElement("div");n.className=`${d}__week-column`;for(let e=6;e<=22;e+=1){const a=document.createElement("div");a.className=`${d}__week-cell`,a.title=`${t.toLocaleDateString()} ${String(e).padStart(2,"0")}:00`,a.addEventListener("click",()=>{this.selectedDate=new Date(t),this.eventForm.startTime=`${String(e).padStart(2,"0")}:00`,this.eventForm.endTime=`${String(e+1).padStart(2,"0")}:00`,this.openAddModal(this.selectedDate)}),n.appendChild(a)}this.eventsForDate(t).forEach(e=>{if(!e.startTime)return;const[t,a]=e.startTime.split(":").map(Number),s=.8*(60*(t-6)+(a||0)),i=(e.endTime||e.startTime).split(":").map(Number),l=60*(i[0]||t)+(i[1]||0),r=60*t+(a||0),o=Math.max(20,48*(l-r)/60),c=document.createElement("div");c.className=[`${d}__week-event`,`${d}__week-event--${e.type}`].filter(Boolean).join(" "),c.textContent=e.title,c.title=e.title,c.style.backgroundColor=e.color||"#17a2b8",c.style.top=`${s}px`,c.style.height=`${o}px`,c.addEventListener("click",t=>this.handleEventClick(e,t)),n.appendChild(c)}),r.appendChild(n)}return i.appendChild(r),e.appendChild(i),e}renderModal(){if(!this.modalEl)return;if(this.modalEl.replaceChildren(),!this.showEventModal)return void this.modalEl.removeAttribute("open");this.modalEl.setAttribute("open","true"),this.modalEl.setAttribute("title",this.isEditing?"일정 편집":"새 일정 추가");const t=document.createElement("div");t.className=`${d}__event-form`;const a=document.createElement("db-input");a.setAttribute("label","제목 *"),a.setAttribute("placeholder",e("일정 제목을 입력하세요")),a.setAttribute("full-width",""),a.setAttribute("value",this.eventForm.title),a.addEventListener("db-input",e=>{this.eventForm.title=e.detail.value});const n=document.createElement("db-input");n.setAttribute("label","설명"),n.setAttribute("placeholder",e("일정 설명을 입력하세요")),n.setAttribute("full-width",""),n.setAttribute("value",this.eventForm.description),n.addEventListener("db-input",e=>{this.eventForm.description=e.detail.value});const l=document.createElement("db-date-picker");l.setAttribute("label","날짜"),l.setAttribute("full-width",""),l.setAttribute("value",i(this.selectedDate)),l.addEventListener("db-change",e=>{const t=s(e.detail.value);t&&(this.selectedDate=t)});const r=document.createElement("db-select");r.setAttribute("label","일정 타입"),r.setAttribute("full-width",""),r.setAttribute("options",JSON.stringify([{value:"meeting",label:e("회의")},{value:"task",label:e("업무")},{value:"reminder",label:e("알림")},{value:"birthday",label:e("생일")},{value:"holiday",label:e("휴일")},{value:"custom",label:e("기타")}])),r.setAttribute("value",this.eventForm.type),r.addEventListener("db-change",e=>{this.eventForm.type=e.detail.value});const o=document.createElement("db-select");o.setAttribute("label","색상"),o.setAttribute("full-width",""),o.setAttribute("options",JSON.stringify([{value:"#17a2b8",label:e("청록")},{value:"#0d6efd",label:e("파랑")},{value:"#198754",label:e("초록")},{value:"#ffc107",label:e("노랑")},{value:"#dc3545",label:e("빨강")},{value:"#6f42c1",label:e("보라")}])),o.setAttribute("value",this.eventForm.color),o.addEventListener("db-change",e=>{this.eventForm.color=e.detail.value});const c=document.createElement("db-time-picker");c.setAttribute("label","시작 시간"),c.setAttribute("full-width",""),c.setAttribute("value",this.eventForm.startTime),c.addEventListener("db-change",e=>{this.eventForm.startTime=e.detail.value});const h=document.createElement("db-time-picker");h.setAttribute("label","종료 시간"),h.setAttribute("full-width",""),h.setAttribute("value",this.eventForm.endTime),h.addEventListener("db-change",e=>{this.eventForm.endTime=e.detail.value}),t.append(a,n,l,r,o,c,h);const m=document.createElement("div");m.className="designbase-wc-modal__body",m.setAttribute("data-modal-part","body"),m.appendChild(t);const u=document.createElement("div");u.className="designbase-wc-modal__footer",u.setAttribute("data-modal-part","footer");const v=document.createElement("div");if(v.className=`${d}__modal-actions`,this.isEditing){const t=document.createElement("db-button");t.setAttribute("variant","destructive"),t.textContent=e("삭제"),t.addEventListener("click",()=>this.deleteEvent()),v.appendChild(t)}const p=document.createElement("div");p.className=`${d}__modal-buttons`;const g=document.createElement("db-button");g.setAttribute("variant","secondary"),g.textContent=e("취소"),g.addEventListener("click",()=>this.closeModal());const b=document.createElement("db-button");b.setAttribute("variant","primary"),b.textContent=this.isEditing?"수정":"저장",b.addEventListener("click",()=>this.saveEvent()),p.append(g,b),v.appendChild(p),u.appendChild(v),this.modalEl.append(m,u)}render(){this.className=d,this.replaceChildren(),this.headerEl&&this.bodyEl&&(this.renderHeader(),this.bodyEl.replaceChildren(),this.bodyEl.appendChild(this.renderMonthView()),this.append(this.headerEl,this.bodyEl),this.renderModal(),this.showEventModal&&this.modalEl&&this.appendChild(this.modalEl))}}customElements.get("db-calendar")||customElements.define("db-calendar",DbCalendar);export{DbCalendar};
|
|
1
|
+
import{dbText as e}from"../core/i18n.js";import{createDbIcon as t,getDbComponentIconSize as a}from"./db-icons.js";import{resolveDateLocale as n,parseISODate as s,toISODate as i}from"./date-picker-utils.js";import"./db-modal.js";import"./db-input.js";import"./db-select.js";import"./db-date-picker.js";import"./db-time-picker.js";import"./db-button.js";const d="designbase-wc-calendar";class DbCalendar extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.currentView="month",this.selectedDate=new Date,this._events=[],this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.draggedEvent=null,this.dragOverDate=null,this.selectedDateRange={start:null,end:null},this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""}}static get observedAttributes(){return["view","current-date","events","locale","show-weekends","highlight-today","show-outside-days"]}connectedCallback(){this.built||this.build(),this.readAttributes(),this.render()}attributeChangedCallback(){this.built&&(this.readAttributes(),this.render())}get locale(){return n(this.getAttribute("locale"))}set locale(e){this.setAttribute("locale",e||"")}get showWeekends(){return"false"!==this.getAttribute("show-weekends")}get highlightToday(){return"false"!==this.getAttribute("highlight-today")}get showOutsideDays(){return"false"!==this.getAttribute("show-outside-days")}get events(){return this._events}set events(e){"string"!=typeof e?(this._events=Array.isArray(e)?e:[],this.setAttribute("events",JSON.stringify(this._events))):this.setAttribute("events",e)}build(){this.built=!0,this.headerEl=document.createElement("div"),this.headerEl.className=`${d}__header`,this.bodyEl=document.createElement("div"),this.bodyEl.className=`${d}__body`,this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","m"),this.modalEl.addEventListener("db-close",()=>this.closeModal())}readAttributes(){this.currentView="month";const e=s(this.getAttribute("current-date"));e&&(this.selectedDate=e);const t=this.getAttribute("events");if(t)try{const e=JSON.parse(t);this._events=Array.isArray(e)?e:[]}catch{this._events=[]}else this._events=[]}isSameDate(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}eventsForDate(e){return this._events.filter(t=>{const a=s(t.date);return!!a&&this.isSameDate(a,e)})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}handleViewChange(e){this.currentView="month",this.emit("db-view-change",{view:e}),this.render()}shiftMonth(e){const t=new Date(this.selectedDate);t.setMonth(t.getMonth()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}shiftYear(e){const t=new Date(this.selectedDate);t.setFullYear(t.getFullYear()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}handleDateClick(e){this.selectedDate=e,this.emit("db-date-click",{date:i(e)}),!this.selectedDateRange.start||this.selectedDateRange.start&&this.selectedDateRange.end?this.selectedDateRange={start:e,end:null}:this.selectedDateRange.start&&!this.selectedDateRange.end&&(e<this.selectedDateRange.start?this.selectedDateRange={start:e,end:this.selectedDateRange.start}:this.selectedDateRange={start:this.selectedDateRange.start,end:e}),this.openAddModal(e)}handleDragStart(e,t){this.draggedEvent=e,t.dataTransfer?.setData("text/plain",e.id),t.dataTransfer?.setData("application/json",JSON.stringify(e)),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")}handleDragOver(e,t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"),this.dragOverDate=e,this.render()}handleDragLeave(e){const t=e.relatedTarget,a=e.currentTarget;a&&t&&a.contains(t)||(this.dragOverDate=null,this.render())}handleDrop(e,t){if(t.preventDefault(),!this.draggedEvent)return;const a={...this.draggedEvent,date:i(e)};this.emit("db-event-edit",{event:a}),this.draggedEvent=null,this.dragOverDate=null,this.render()}handleDragEnd(){this.draggedEvent=null,this.dragOverDate=null,this.render()}handleEventClick(e,t){t.stopPropagation(),this.selectedEvent=e,this.isEditing=!0;const a=s(e.date);a&&(this.selectedDate=a),this.eventForm={title:e.title,description:e.description||"",startTime:e.startTime||"09:00",endTime:e.endTime||"10:00",type:e.type,color:e.color||"#17a2b8",isAllDay:e.isAllDay||!1,location:e.location||""},this.emit("db-event-click",{event:e}),this.showEventModal=!0,this.render()}openAddModal(e){this.selectedDate=e,this.selectedEvent=null,this.isEditing=!1,this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""},this.showEventModal=!0,this.render()}closeModal(){this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.render()}saveEvent(){if(!this.eventForm.title.trim())return void window.alert("제목을 입력해주세요.");const e={title:this.eventForm.title.trim(),description:this.eventForm.description,date:i(this.selectedDate),startTime:this.eventForm.startTime,endTime:this.eventForm.endTime,type:this.eventForm.type,color:this.eventForm.color,isAllDay:this.eventForm.isAllDay,location:this.eventForm.location};if(this.isEditing&&this.selectedEvent){const t={...this.selectedEvent,...e};this.emit("db-event-edit",{event:t})}else this.emit("db-event-add",{event:e});this.closeModal()}deleteEvent(){this.selectedEvent&&window.confirm("정말로 이 일정을 삭제하시겠습니까?")&&(this.emit("db-event-delete",{eventId:this.selectedEvent.id}),this.closeModal())}renderHeader(){if(!this.headerEl)return;this.headerEl.replaceChildren();const n=document.createElement("div");n.className=`${d}__navigation`;const s=a("m"),i=document.createElement("button");i.type="button",i.className=`${d}__nav-button`,i.setAttribute("aria-label",e("이전")),i.appendChild(t("chevron-left",s)),i.addEventListener("click",()=>{this.shiftMonth(-1)});const l=document.createElement("div");l.className=`${d}__title`,l.textContent=this.selectedDate.toLocaleDateString(this.locale,{year:"numeric",month:"long"});const r=document.createElement("button");r.type="button",r.className=`${d}__nav-button`,r.setAttribute("aria-label",e("다음")),r.appendChild(t("chevron-right",s)),r.addEventListener("click",()=>{this.shiftMonth(1)}),n.append(i,l,r),this.headerEl.appendChild(n)}renderMonthView(){const e=document.createElement("div");e.className=`${d}__month-view`;const t=document.createElement("div");t.className=`${d}__weekdays`,["일","월","화","수","목","금","토"].forEach(e=>{const a=document.createElement("div");a.className=`${d}__weekday`,a.textContent=e,t.appendChild(a)}),e.appendChild(t);const a=document.createElement("div");a.className=`${d}__days`;const n=this.selectedDate.getFullYear(),s=this.selectedDate.getMonth(),i=new Date(n,s,1),l=new Date(i);l.setDate(l.getDate()-i.getDay());const r=new Date;for(let e=0;e<42;e+=1){const t=new Date(l);t.setDate(l.getDate()+e);const n=t.getMonth()===s;if(!this.showOutsideDays&&!n)continue;const i=0===t.getDay()||6===t.getDay();if(!this.showWeekends&&i)continue;const o=document.createElement("div"),c=this.selectedDateRange.start&&this.selectedDateRange.end&&t>=this.selectedDateRange.start&&t<=this.selectedDateRange.end,h=this.selectedDateRange.start&&t.toDateString()===this.selectedDateRange.start.toDateString(),m=this.selectedDateRange.end&&t.toDateString()===this.selectedDateRange.end.toDateString(),u=Boolean(c&&!h&&!m);o.className=[`${d}__day`,n&&`${d}__day--current-month`,this.highlightToday&&t.toDateString()===r.toDateString()&&`${d}__day--today`,this.isSameDate(t,this.selectedDate)&&`${d}__day--selected`,h&&`${d}__day--selected--start`,m&&`${d}__day--selected--end`,u&&`${d}__day--selected--middle`,!this.showWeekends&&i&&`${d}__day--weekend`].filter(Boolean).join(" "),o.addEventListener("click",()=>this.handleDateClick(t));const v=document.createElement("span");v.className=`${d}__day-number`,v.textContent=String(t.getDate()),o.appendChild(v);const p=this.eventsForDate(t);if(p.length){const e=document.createElement("div");if(e.className=`${d}__day-events`,p.slice(0,2).forEach(t=>{const a=document.createElement("div");a.className=[`${d}__event-bar`,`${d}__event-bar--${t.type}`].filter(Boolean).join(" "),t.color&&(a.style.backgroundColor=t.color),this.draggedEvent?.id===t.id&&a.classList.add(`${d}__event-bar--dragging`),a.title=t.title,a.draggable=!0;const n=document.createElement("span");n.className=`${d}__event-title`,n.textContent=t.title,a.appendChild(n),a.addEventListener("click",e=>this.handleEventClick(t,e)),a.addEventListener("dragstart",e=>this.handleDragStart(t,e)),a.addEventListener("dragend",()=>this.handleDragEnd()),e.appendChild(a)}),p.length>2){const t=document.createElement("div");t.className=`${d}__more-events`,t.textContent=`+${p.length-2} more`,e.appendChild(t)}o.appendChild(e)}const g=document.createElement("div");g.className=[`${d}__drop-zone`,this.dragOverDate&&this.isSameDate(this.dragOverDate,t)&&`${d}__drop-zone--active`].filter(Boolean).join(" "),g.addEventListener("dragover",e=>this.handleDragOver(t,e)),g.addEventListener("dragleave",e=>this.handleDragLeave(e)),g.addEventListener("drop",e=>this.handleDrop(t,e)),o.appendChild(g),a.appendChild(o)}return e.appendChild(a),e}renderYearView(){const e=document.createElement("div");e.className=`${d}__year-view`;const t=this.selectedDate.getFullYear();for(let a=0;a<12;a+=1){const n=new Date(t,a,1),i=this._events.filter(e=>{const n=s(e.date);return n&&n.getFullYear()===t&&n.getMonth()===a}),l=document.createElement("div");l.className=`${d}__year-month`,l.addEventListener("click",()=>{this.selectedDate=n,this.handleViewChange("month")});const r=document.createElement("h3");if(r.className=`${d}__year-month-title`,r.textContent=n.toLocaleDateString(this.locale,{month:"long"}),l.appendChild(r),i.length){const e=document.createElement("div");if(e.className=`${d}__year-month-events`,i.slice(0,4).forEach(t=>{const a=document.createElement("span");a.className=[`${d}__year-event`,`${d}__year-event--${t.type}`].join(" "),t.color&&(a.style.backgroundColor=t.color),e.appendChild(a)}),i.length>4){const t=document.createElement("span");t.className=`${d}__year-more-events`,t.textContent=`+${i.length-4} more`,e.appendChild(t)}l.appendChild(e)}e.appendChild(l)}return e}renderWeekView(){const e=document.createElement("div");e.className=`${d}__week-view`;const t=new Date,a=new Date(this.selectedDate);a.setDate(this.selectedDate.getDate()-this.selectedDate.getDay());const n=document.createElement("div");n.className=`${d}__week-header`;const s=document.createElement("div");s.className=`${d}__time-column-header`,n.appendChild(s);for(let e=0;e<7;e+=1){const s=new Date(a);s.setDate(a.getDate()+e);const i=document.createElement("div");i.className=[`${d}__week-day-header`,s.toDateString()===t.toDateString()&&`${d}__week-day-header--today`].filter(Boolean).join(" ");const l=document.createElement("span");l.className=`${d}__week-day-name`,l.textContent=s.toLocaleDateString(this.locale,{weekday:"short"});const r=document.createElement("span");r.className=`${d}__week-day-number`,r.textContent=String(s.getDate()),i.append(l,r),n.appendChild(i)}e.appendChild(n);const i=document.createElement("div");i.className=`${d}__week-grid`;const l=document.createElement("div");l.className=`${d}__week-time-column`;for(let e=6;e<=22;e+=1){const t=document.createElement("div");t.className=`${d}__time-slot`;const a=document.createElement("span");a.className=`${d}__time-label`,a.textContent=`${String(e).padStart(2,"0")}:00`,t.appendChild(a),l.appendChild(t)}i.appendChild(l);const r=document.createElement("div");r.className=`${d}__week-columns`;for(let e=0;e<7;e+=1){const t=new Date(a);t.setDate(a.getDate()+e);const n=document.createElement("div");n.className=`${d}__week-column`;for(let e=6;e<=22;e+=1){const a=document.createElement("div");a.className=`${d}__week-cell`,a.title=`${t.toLocaleDateString()} ${String(e).padStart(2,"0")}:00`,a.addEventListener("click",()=>{this.selectedDate=new Date(t),this.eventForm.startTime=`${String(e).padStart(2,"0")}:00`,this.eventForm.endTime=`${String(e+1).padStart(2,"0")}:00`,this.openAddModal(this.selectedDate)}),n.appendChild(a)}this.eventsForDate(t).forEach(e=>{if(!e.startTime)return;const[t,a]=e.startTime.split(":").map(Number),s=.8*(60*(t-6)+(a||0)),i=(e.endTime||e.startTime).split(":").map(Number),l=60*(i[0]||t)+(i[1]||0),r=60*t+(a||0),o=Math.max(20,48*(l-r)/60),c=document.createElement("div");c.className=[`${d}__week-event`,`${d}__week-event--${e.type}`].filter(Boolean).join(" "),c.textContent=e.title,c.title=e.title,c.style.backgroundColor=e.color||"#17a2b8",c.style.top=`${s}px`,c.style.height=`${o}px`,c.addEventListener("click",t=>this.handleEventClick(e,t)),n.appendChild(c)}),r.appendChild(n)}return i.appendChild(r),e.appendChild(i),e}renderModal(){if(!this.modalEl)return;if(this.modalEl.replaceChildren(),!this.showEventModal)return void this.modalEl.removeAttribute("open");this.modalEl.setAttribute("open","true"),this.modalEl.setAttribute("title",this.isEditing?"일정 편집":"새 일정 추가");const t=document.createElement("div");t.className=`${d}__event-form`;const a=document.createElement("db-input");a.setAttribute("label","제목 *"),a.setAttribute("placeholder",e("일정 제목을 입력하세요")),a.setAttribute("full-width",""),a.setAttribute("value",this.eventForm.title),a.addEventListener("db-input",e=>{this.eventForm.title=e.detail.value});const n=document.createElement("db-input");n.setAttribute("label","설명"),n.setAttribute("placeholder",e("일정 설명을 입력하세요")),n.setAttribute("full-width",""),n.setAttribute("value",this.eventForm.description),n.addEventListener("db-input",e=>{this.eventForm.description=e.detail.value});const l=document.createElement("db-date-picker");l.setAttribute("label","날짜"),l.setAttribute("full-width",""),l.setAttribute("value",i(this.selectedDate)),l.addEventListener("db-change",e=>{const t=s(e.detail.value);t&&(this.selectedDate=t)});const r=document.createElement("db-select");r.setAttribute("label","일정 타입"),r.setAttribute("full-width",""),r.setAttribute("options",JSON.stringify([{value:"meeting",label:e("회의")},{value:"task",label:e("업무")},{value:"reminder",label:e("알림")},{value:"birthday",label:e("생일")},{value:"holiday",label:e("휴일")},{value:"custom",label:e("기타")}])),r.setAttribute("value",this.eventForm.type),r.addEventListener("db-change",e=>{this.eventForm.type=e.detail.value});const o=document.createElement("db-select");o.setAttribute("label","색상"),o.setAttribute("full-width",""),o.setAttribute("options",JSON.stringify([{value:"#17a2b8",label:e("청록")},{value:"#0d6efd",label:e("파랑")},{value:"#198754",label:e("초록")},{value:"#ffc107",label:e("노랑")},{value:"#dc3545",label:e("빨강")},{value:"#6f42c1",label:e("보라")}])),o.setAttribute("value",this.eventForm.color),o.addEventListener("db-change",e=>{this.eventForm.color=e.detail.value});const c=document.createElement("db-time-picker");c.setAttribute("label","시작 시간"),c.setAttribute("full-width",""),c.setAttribute("value",this.eventForm.startTime),c.addEventListener("db-change",e=>{this.eventForm.startTime=e.detail.value});const h=document.createElement("db-time-picker");h.setAttribute("label","종료 시간"),h.setAttribute("full-width",""),h.setAttribute("value",this.eventForm.endTime),h.addEventListener("db-change",e=>{this.eventForm.endTime=e.detail.value}),t.append(a,n,l,r,o,c,h);const m=document.createElement("div");m.className="designbase-wc-modal__body",m.setAttribute("data-modal-part","body"),m.appendChild(t);const u=document.createElement("div");u.className="designbase-wc-modal__footer",u.setAttribute("data-modal-part","footer");const v=document.createElement("div");if(v.className=`${d}__modal-actions`,this.isEditing){const t=document.createElement("db-button");t.setAttribute("variant","destructive"),t.textContent=e("삭제"),t.addEventListener("click",()=>this.deleteEvent()),v.appendChild(t)}const p=document.createElement("div");p.className=`${d}__modal-buttons`;const g=document.createElement("db-button");g.setAttribute("variant","secondary"),g.textContent=e("취소"),g.addEventListener("click",()=>this.closeModal());const b=document.createElement("db-button");b.setAttribute("variant","primary"),b.textContent=this.isEditing?"수정":"저장",b.addEventListener("click",()=>this.saveEvent()),p.append(g,b),v.appendChild(p),u.appendChild(v),this.modalEl.append(m,u)}render(){this.className=d,this.replaceChildren(),this.headerEl&&this.bodyEl&&(this.renderHeader(),this.bodyEl.replaceChildren(),this.bodyEl.appendChild(this.renderMonthView()),this.append(this.headerEl,this.bodyEl),this.renderModal(),this.showEventModal&&this.modalEl&&this.appendChild(this.modalEl))}}customElements.get("db-calendar")||customElements.define("db-calendar",DbCalendar);export{DbCalendar};
|
|
@@ -13,6 +13,8 @@ declare class DbCarousel extends HTMLElement {
|
|
|
13
13
|
static get observedAttributes(): string[];
|
|
14
14
|
get items(): DbCarouselItem[];
|
|
15
15
|
set items(value: DbCarouselItem[] | string);
|
|
16
|
+
private unsubscribeLocale?;
|
|
17
|
+
private syncLocale;
|
|
16
18
|
connectedCallback(): void;
|
|
17
19
|
disconnectedCallback(): void;
|
|
18
20
|
attributeChangedCallback(name: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as e}from"./db-icons.js";import{t}from"../core/i18n.js";import{b as
|
|
1
|
+
import{createDbIcon as e}from"./db-icons.js";import{t,subscribeDbLocale as s}from"../core/i18n.js";import{b as i}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js";import{a as n}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-GM4TCAP5.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{CAROUSEL_SIZES as a,CAROUSEL_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbCarousel extends HTMLElement{constructor(){super(...arguments),this.currentIndex=0,this.isAutoPlaying=!1,this.syncLocale=()=>{this.setAttribute("aria-roledescription",t("carousel.role")),this.querySelectorAll(".designbase-wc-carousel__slide").forEach(e=>e.setAttribute("aria-roledescription",t("carousel.slide"))),this.querySelector(".designbase-wc-carousel__nav-button--prev")?.setAttribute("aria-label",t("carousel.previous")),this.querySelector(".designbase-wc-carousel__nav-button--next")?.setAttribute("aria-label",t("carousel.next"))}}static get observedAttributes(){return["items","size","variant","theme","transition","auto-play","auto-play-interval","infinite","show-navigation","show-indicators","indicator-style","show-auto-play-control","show-title","show-description","disabled","readonly"]}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.unsubscribeLocale=s(this.syncLocale),this.style.display="block",this.clampCurrentIndex(),this.isAutoPlaying=this.getBool("auto-play"),this.render()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.destroyEngine()}attributeChangedCallback(e){this.isConnected&&("items"===e&&this.clampCurrentIndex(),"auto-play"!==e&&"auto-play-interval"!==e||(this.isAutoPlaying=this.getBool("auto-play")),this.render())}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const s=this.getAttribute(e);return""===s||"true"===s}clampCurrentIndex(){this.currentIndex>=this.items.length&&(this.currentIndex=0)}destroyEngine(){const e=this.isAutoPlaying;this.autoplay?.destroy(),this.autoplay=void 0,this.engine?.destroy(),this.engine=void 0,this.isAutoPlaying=e}getIndicatorType(){if(this.getBool("show-auto-play-control",!0)&&this.getBool("show-indicators",!0)&&this.items.length>1)return"combined";const e=this.getAttribute("indicator-style")||"dots";return"lines"===e?"line":"numbers"===e?"numbers":"dots"}getIndicatorSize(){const e=o(this.getAttribute("size"),a,"m");return"l"===e||"xl"===e?"m":"s"}goTo(e){this.getBool("disabled")||this.getBool("readonly")||e<0||e>=this.items.length||this.engine?.goTo(e)}goToPrev(){this.getBool("disabled")||this.getBool("readonly")||this.engine?.prev()}goToNext(){this.getBool("disabled")||this.getBool("readonly")||this.engine?.next()}render(){this.destroyEngine();const s=o(this.getAttribute("size"),a,"m"),l=o(this.getAttribute("variant"),r,"default"),c=this.getAttribute("theme")||"light",d=this.getAttribute("transition")||"slide",u=this.getBool("show-navigation",!0),h=this.getBool("show-indicators",!0),g=this.getBool("show-auto-play-control",!0),b=this.getBool("show-title",!0),m=this.getBool("show-description",!0),p=this.getBool("disabled"),y=this.getBool("readonly"),v=this.getAttribute("indicator-style")||"dots",A=g&&h&&this.items.length>1;this.className=["designbase-wc-carousel","db-slide",`designbase-wc-carousel--size-${s}`,`designbase-wc-carousel--variant-${l}`,`designbase-wc-carousel--theme-${c}`,`designbase-wc-carousel--transition-${d}`,`designbase-wc-carousel--indicator-${v}`,p&&"designbase-wc-carousel--disabled",y&&"designbase-wc-carousel--readonly"].filter(Boolean).join(" ");const _=document.createElement("div");_.className="designbase-wc-carousel__container";const w=document.createElement("div");if(w.className="designbase-wc-carousel__track db-slide__viewport",(p||y)&&(w.style.overflowX="hidden"),this.items.forEach((e,t)=>{const s=document.createElement("div");s.className="designbase-wc-carousel__slide"+(t===this.currentIndex?" designbase-wc-carousel__slide--active":""),s.style.flex="0 0 100%",s.style.width="100%",s.style.height="100%",s.style.minWidth="0";const i=e.image?"#ffffff":"";if(i&&(s.style.color=i),e.image){const i=document.createElement("div");i.className="designbase-wc-carousel__slide-image";const n=document.createElement("img");n.className="designbase-wc-carousel__slide-img",n.src=e.image,n.alt=e.alt||e.title||`Slide ${t+1}`,i.append(n),s.append(i)}if(b&&e.title||m&&e.description){const t=document.createElement("div");if(t.className="designbase-wc-carousel__slide-info",i&&(t.style.color=i),b&&e.title){const s=document.createElement("h3");s.className="designbase-wc-carousel__slide-title",s.textContent=e.title,i&&(s.style.color=i),t.append(s)}if(m&&e.description){const s=document.createElement("p");s.className="designbase-wc-carousel__slide-description",s.textContent=e.description,i&&(s.style.color=i),t.append(s)}s.append(t)}s.addEventListener("click",()=>{p||y||this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:e,index:t},bubbles:!0,composed:!0}))}),w.append(s)}),_.append(w),u&&this.items.length>1){const s=document.createElement("button");s.className="designbase-wc-carousel__nav-button designbase-wc-carousel__nav-button--prev",s.type="button",s.setAttribute("aria-label",t("carousel.previous")),s.append(e("chevron-left",20)),s.disabled=p||y,s.addEventListener("click",()=>this.goToPrev());const i=document.createElement("button");i.className="designbase-wc-carousel__nav-button designbase-wc-carousel__nav-button--next",i.type="button",i.setAttribute("aria-label",t("carousel.next")),i.append(e("chevron-right",20)),i.disabled=p||y,i.addEventListener("click",()=>this.goToNext()),_.append(s,i)}const x=[_];if(h&&this.items.length>1){const e=document.createElement("div");e.className="designbase-wc-carousel__controls";const t=document.createElement("div");t.className="designbase-wc-carousel__indicators";const s=document.createElement("db-indicator");s.setAttribute("current",String(this.currentIndex)),s.setAttribute("total",String(this.items.length)),s.setAttribute("type",this.getIndicatorType()),s.setAttribute("size",this.getIndicatorSize()),s.setAttribute("clickable",""),A&&(s.setAttribute("timer",""),s.setAttribute("progress","0"),s.setAttribute("timer-duration",String(Math.max(1e3,Number(this.getAttribute("auto-play-interval")||5e3)))),s.setAttribute("auto-roll","false"),this.isAutoPlaying?s.setAttribute("playing",""):s.removeAttribute("playing"),(p||y)&&s.setAttribute("playback-disabled","")),s.addEventListener("db-step-click",e=>{const t=e;this.goTo(t.detail.index)}),s.addEventListener("db-playing-change",e=>{const t=e;this.isAutoPlaying=t.detail.playing,p||y||(this.isAutoPlaying?this.autoplay?.play():this.autoplay?.pause())}),t.append(s),e.append(t),x.push(e)}this.replaceChildren(...x),this.engine=i(this,{startIndex:this.currentIndex,slidesPerView:1,gap:0,rewind:this.getBool("infinite",!0),drag:!p&&!y,keyboard:!p&&!y,label:this.getAttribute("aria-label")||"Carousel"});const sync=()=>{this.syncLocale();const e=this.engine.getState(),t=e.index!==this.currentIndex;this.currentIndex=e.index,w.querySelectorAll(".designbase-wc-carousel__slide").forEach((t,s)=>{t.classList.toggle("designbase-wc-carousel__slide--active",e.visible.includes(s))});const s=this.querySelector("db-indicator");s?.getAttribute("current")!==String(e.index)&&s?.setAttribute("current",String(e.index));const i=this.querySelector(".designbase-wc-carousel__nav-button--prev"),n=this.querySelector(".designbase-wc-carousel__nav-button--next");i&&(i.disabled=p||y||!e.canPrev),n&&(n.disabled=p||y||!e.canNext),t&&this.dispatchEvent(new CustomEvent("db-slide-change",{detail:{index:e.index},bubbles:!0,composed:!0}))};this.engine.on("change",sync),this.engine.on("refresh",sync),sync(),this.autoplay=n(this.engine,{delay:Math.max(1e3,Number(this.getAttribute("auto-play-interval")||5e3)),playOnInit:this.isAutoPlaying&&!p&&!y}),this.autoplay.onProgress(e=>{A&&this.querySelector("db-indicator")?.setAttribute("progress",String(e.progress))}),this.autoplay.onChange(e=>{p||y||(this.isAutoPlaying=e);const t=this.querySelector("db-indicator");A&&t?.toggleAttribute("playing",e)})}}customElements.get("db-carousel")||customElements.define("db-carousel",DbCarousel);export{DbCarousel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as t,dbFormat as e}from"../core/i18n.js";import{isDbIconName as s,createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";import"./db-voice-control.js";const DEFAULT_ATTACH_OPTIONS=()=>[{id:"image",label:t("사진·이미지"),icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:t("동영상"),icon:"video",accept:"video/*",multiple:!0},{id:"file",label:t("문서·파일"),icon:"file-new",accept:"",multiple:!0},{id:"camera",label:t("카메라 촬영"),icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const a={image:"gallery",video:"video",file:"file-new"};let n=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=DEFAULT_ATTACH_OPTIONS(),this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>"Escape"===t.key&&this.voiceActive?(t.preventDefault(),void this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:"cancel"},bubbles:!0,composed:!0}))):"Escape"===t.key&&this.attachMenuOpen?(t.preventDefault(),void this.closeAttachMenu()):void("Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())),this.handleSendClick=()=>{this.disabled||this.voiceActive||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label","voice-state","voice-message","voice-disabled"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:DEFAULT_ATTACH_OPTIONS(),this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==t?this.sync():this.renderSendButton()}}build(){this.built=!0,this.className="designbase-wc-chat-composer",this.replaceChildren();const e=document.createElement("div");e.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const s=document.createElement("div");s.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),s.append(this.field);const i=document.createElement("div");i.className="designbase-wc-chat-composer__toolbar";const a=document.createElement("div");a.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label",t("첨부")),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",a.append(this.attachWrap,this.toolsEl);const n=document.createElement("div");n.className="designbase-wc-chat-composer__trailing",this.micBtn=document.createElement("db-voice-control"),this.micBtn.setAttribute("compact","");for(const t of["start","stop","cancel"])this.micBtn.addEventListener(`db-${t}`,e=>{e.stopPropagation(),this.disabled||this.streaming||this.hasAttribute("voice-disabled")||this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:t},bubbles:!0,composed:!0}))});this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),n.append(this.micBtn,this.sendBtn),i.append(a,n),e.append(this.attachmentsEl,s,i),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true"),this.dropOverlay.innerHTML='<span class="designbase-wc-chat-composer__drop-label">파일을 놓으면 첨부됩니다</span>',this.append(e,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=this.getAttribute("placeholder")||"메시지를 입력하세요…",this.field.disabled=this.disabled,this.field.readOnly=this.voiceActive;const t=this.getAttribute("max-length");t?this.field.maxLength=Number(t):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.micBtn.setAttribute("state",this.getAttribute("voice-state")||"idle"),this.micBtn.setAttribute("message",this.getAttribute("voice-message")||""),this.micBtn.toggleAttribute("disabled",this.disabled||this.streaming||this.hasAttribute("voice-disabled")),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const t of this._tools){const e=document.createElement("db-chip");e.setAttribute("label",t.label),e.setAttribute("size","s"),e.setAttribute("clickable",""),e.setAttribute("variant",t.active?"primary":"default"),t.icon&&s(t.icon)&&e.setAttribute("start-icon",t.icon),e.setAttribute("aria-pressed",String(!!t.active)),e.addEventListener("db-click",()=>{this.disabled||(t.active=!t.active,e.setAttribute("variant",t.active?"primary":"default"),e.setAttribute("aria-pressed",String(!!t.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:t.id,active:!!t.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(e)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const t of this._attachOptions){const e=document.createElement("button");e.type="button",e.className="designbase-wc-chat-composer__attach-item",e.setAttribute("role","menuitem");const a=document.createElement("span");a.className="designbase-wc-chat-composer__attach-item-icon",t.icon&&s(t.icon)&&a.append(i(t.icon,18));const n=document.createElement("span");n.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=t.label,n.append(h),t.description){const e=document.createElement("span");e.className="designbase-wc-chat-composer__attach-item-desc",e.textContent=t.description,n.append(e)}e.append(a,n),e.addEventListener("click",()=>this.chooseAttachOption(t)),this.attachMenu.append(e)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const s=document.createElement("div");s.className="designbase-wc-chat-composer__thumb";const a=document.createElement("img");a.src=t.preview,a.alt=t.name;const n=document.createElement("button");n.type="button",n.className="designbase-wc-chat-composer__thumb-remove",n.setAttribute("aria-label",e("{0} 제거",[t.name])),n.append(i("close",12)),n.addEventListener("click",()=>this.removeAttachment(t.id)),s.append(a,n),this.attachmentsEl.append(s);continue}const s=document.createElement("db-chip");s.setAttribute("label",t.name),s.setAttribute("size","s"),s.setAttribute("variant","neutral"),s.setAttribute("deletable",""),s.setAttribute("start-icon",a[t.kind]),s.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(s)}this.syncSendState()}renderSendButton(){const t=this.streaming;this.sendBtn.setAttribute("variant",t?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",t?"stop":"send"),this.sendBtn.setAttribute("aria-label",t?"생성 중지":"전송"),this.syncSendState()}get voiceActive(){return this.hasAttribute("voice")&&["starting","listening","stopping"].includes(this.getAttribute("voice-state")||"idle")}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||this.voiceActive||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${n+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming||this.voiceActive)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${n+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
|
|
1
|
+
import{labelFrom as t,dbText as e,dbFormat as s}from"../core/i18n.js";import{setHostClasses as i}from"../core/host-class.js";import{isDbIconName as a,createDbIcon as n}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";import"./db-voice-control.js";const DEFAULT_ATTACH_OPTIONS=()=>[{id:"image",label:e("사진·이미지"),icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:e("동영상"),icon:"video",accept:"video/*",multiple:!0},{id:"file",label:e("문서·파일"),icon:"file-new",accept:"",multiple:!0},{id:"camera",label:e("카메라 촬영"),icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const h={image:"gallery",video:"video",file:"file-new"};let c=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=DEFAULT_ATTACH_OPTIONS(),this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>"Escape"===t.key&&this.voiceActive?(t.preventDefault(),void this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:"cancel"},bubbles:!0,composed:!0}))):"Escape"===t.key&&this.attachMenuOpen?(t.preventDefault(),void this.closeAttachMenu()):void("Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())),this.handleSendClick=()=>{this.disabled||this.voiceActive||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label","stop-label","attach-label","voice-state","voice-message","voice-disabled"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:DEFAULT_ATTACH_OPTIONS(),this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(e){if(this.built){if("value"===e){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==e&&"send-label"!==e&&"stop-label"!==e?"attach-label"!==e?this.sync():this.attachBtn.setAttribute("aria-label",t(this,"attach-label","chatComposer.attach")):this.renderSendButton()}}build(){this.built=!0,i(this,["designbase-wc-chat-composer"]),this.replaceChildren();const s=document.createElement("div");s.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const a=document.createElement("div");a.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),a.append(this.field);const n=document.createElement("div");n.className="designbase-wc-chat-composer__toolbar";const h=document.createElement("div");h.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label",t(this,"attach-label","chatComposer.attach")),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",h.append(this.attachWrap,this.toolsEl);const c=document.createElement("div");c.className="designbase-wc-chat-composer__trailing",this.micBtn=document.createElement("db-voice-control"),this.micBtn.setAttribute("compact","");for(const t of["start","stop","cancel"])this.micBtn.addEventListener(`db-${t}`,e=>{e.stopPropagation(),this.disabled||this.streaming||this.hasAttribute("voice-disabled")||this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:t},bubbles:!0,composed:!0}))});this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),c.append(this.micBtn,this.sendBtn),n.append(h,c),s.append(this.attachmentsEl,a,n),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className="designbase-wc-chat-composer__drop-label",r.textContent=e("파일을 놓으면 첨부됩니다"),this.dropOverlay.append(r),this.append(s,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=t(this,"placeholder","chatComposer.placeholder"),this.field.disabled=this.disabled,this.field.readOnly=this.voiceActive;const e=this.getAttribute("max-length");e?this.field.maxLength=Number(e):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.micBtn.setAttribute("state",this.getAttribute("voice-state")||"idle"),this.micBtn.setAttribute("message",this.getAttribute("voice-message")||""),this.micBtn.toggleAttribute("disabled",this.disabled||this.streaming||this.hasAttribute("voice-disabled")),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const t of this._tools){const e=document.createElement("db-chip");e.setAttribute("label",t.label),e.setAttribute("size","s"),e.setAttribute("clickable",""),e.setAttribute("variant",t.active?"primary":"default"),t.icon&&a(t.icon)&&e.setAttribute("start-icon",t.icon),e.setAttribute("aria-pressed",String(!!t.active)),e.addEventListener("db-click",()=>{this.disabled||(t.active=!t.active,e.setAttribute("variant",t.active?"primary":"default"),e.setAttribute("aria-pressed",String(!!t.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:t.id,active:!!t.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(e)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const t of this._attachOptions){const e=document.createElement("button");e.type="button",e.className="designbase-wc-chat-composer__attach-item",e.setAttribute("role","menuitem");const s=document.createElement("span");s.className="designbase-wc-chat-composer__attach-item-icon",t.icon&&a(t.icon)&&s.append(n(t.icon,18));const i=document.createElement("span");i.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=t.label,i.append(h),t.description){const e=document.createElement("span");e.className="designbase-wc-chat-composer__attach-item-desc",e.textContent=t.description,i.append(e)}e.append(s,i),e.addEventListener("click",()=>this.chooseAttachOption(t)),this.attachMenu.append(e)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const e=document.createElement("div");e.className="designbase-wc-chat-composer__thumb";const i=document.createElement("img");i.src=t.preview,i.alt=t.name;const a=document.createElement("button");a.type="button",a.className="designbase-wc-chat-composer__thumb-remove",a.setAttribute("aria-label",s("{0} 제거",[t.name])),a.append(n("close",12)),a.addEventListener("click",()=>this.removeAttachment(t.id)),e.append(i,a),this.attachmentsEl.append(e);continue}const e=document.createElement("db-chip");e.setAttribute("label",t.name),e.setAttribute("size","s"),e.setAttribute("variant","neutral"),e.setAttribute("deletable",""),e.setAttribute("start-icon",h[t.kind]),e.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(e)}this.syncSendState()}renderSendButton(){const e=this.streaming;this.sendBtn.setAttribute("variant",e?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",e?"stop":"send"),this.sendBtn.setAttribute("aria-label",e?t(this,"stop-label","chatComposer.stop"):t(this,"send-label","chatComposer.send")),this.syncSendState()}get voiceActive(){return this.hasAttribute("voice")&&["starting","listening","stopping"].includes(this.getAttribute("voice-state")||"idle")}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||this.voiceActive||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${c+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming||this.voiceActive)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${c+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
|
|
@@ -6,9 +6,22 @@ declare class DbCheckbox extends HTMLElement {
|
|
|
6
6
|
private labelEl?;
|
|
7
7
|
private built;
|
|
8
8
|
private userInteracted;
|
|
9
|
+
private resetChecked?;
|
|
9
10
|
private readonly cleanups;
|
|
11
|
+
focus(options?: FocusOptions): void;
|
|
12
|
+
get name(): string;
|
|
13
|
+
set name(value: string);
|
|
14
|
+
get value(): string;
|
|
15
|
+
set value(value: string);
|
|
16
|
+
get defaultChecked(): boolean;
|
|
17
|
+
set defaultChecked(value: boolean);
|
|
18
|
+
get defaultSelected(): boolean;
|
|
19
|
+
set defaultSelected(value: boolean);
|
|
20
|
+
private upgradeProperties;
|
|
10
21
|
get checked(): boolean;
|
|
11
22
|
set checked(value: boolean);
|
|
23
|
+
get selected(): boolean;
|
|
24
|
+
set selected(value: boolean);
|
|
12
25
|
get indeterminate(): boolean;
|
|
13
26
|
set indeterminate(value: boolean);
|
|
14
27
|
get disabled(): boolean;
|
|
@@ -25,7 +38,8 @@ declare class DbCheckbox extends HTMLElement {
|
|
|
25
38
|
/** form.reset() 이후 네이티브 input 의 실제 상태를 호스트 attribute 로 되돌린다 */
|
|
26
39
|
private syncAfterReset;
|
|
27
40
|
attributeChangedCallback(name: string): void;
|
|
28
|
-
|
|
41
|
+
get hasLabel(): boolean;
|
|
42
|
+
set hasLabel(value: boolean);
|
|
29
43
|
private build;
|
|
30
44
|
private handleChange;
|
|
31
45
|
/**
|