@designbasekorea/ui-wc 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +9 -0
- package/dist/esm/components/db-color-picker.d.ts +1 -0
- package/dist/esm/components/db-color-picker.js +1 -1
- package/dist/esm/components/db-color-swatch.d.ts +43 -0
- package/dist/esm/components/db-color-swatch.js +1 -0
- package/dist/esm/components/db-range-slider.js +1 -1
- package/dist/esm/components/db-search-bar.js +1 -1
- package/dist/esm/components/db-segment-control.js +1 -1
- package/dist/esm/components/db-sidebar.js +1 -1
- package/dist/esm/components/db-tabs.d.ts +3 -0
- package/dist/esm/components/db-tabs.js +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +47 -2
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +71 -4
- package/dist/react/index.esm.js +1 -1
- package/package.json +1 -1
- /package/dist/chunks/{lottie-672879dc.js → lottie-78a72482.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# 변경 이력
|
|
2
2
|
|
|
3
|
+
## 0.8.0 - 2026-07-19
|
|
4
|
+
|
|
5
|
+
### 추가
|
|
6
|
+
|
|
7
|
+
- ColorSwatch 컴포넌트: 프리셋 색상 칩(rounded · circle), 마우스 오버 시 색상 이름 표시, 무지개 그라데이션 커스텀 칩
|
|
8
|
+
- ColorSwatch 커스텀 칩 클릭 시 드롭다운(`custom-type="dropdown"`) 또는 모달(`custom-type="modal"`)로 색상 선택
|
|
9
|
+
- ColorPicker `trigger="swatch"`: 입력 필드 대신 원형 색상 스와치를 트리거로 사용
|
|
10
|
+
- ColorSwatch React wrapper 및 Web Component 공개 API
|
|
11
|
+
|
|
12
|
+
### 개선
|
|
13
|
+
|
|
14
|
+
- ColorPicker 모달을 기존 Modal 컴포넌트 규격에 맞춰 정리 (body 패딩, footer 구분선·액션 버튼 우측 정렬)
|
|
15
|
+
|
|
16
|
+
### 수정
|
|
17
|
+
|
|
18
|
+
- ColorSwatch 스와치 트리거 드롭다운이 외부 클릭으로 닫히지 않던 문제
|
|
19
|
+
- ColorPicker 모달 body·footer에 스타일 클래스가 누락되어 레이아웃이 어긋나던 문제
|
|
20
|
+
|
|
21
|
+
## 0.7.3 - 2026-07-18
|
|
22
|
+
|
|
23
|
+
### 추가
|
|
24
|
+
|
|
25
|
+
- Sidebar `variant`(외형: `default` · `wrapper`) · `theme`(색상: `default` · `dark` · `light`) 프롭 체계 정리
|
|
26
|
+
- SegmentControl `appearance`(`default` · `pill` · `rounded`), SearchBar `appearance`(`default` · `pill`)
|
|
27
|
+
|
|
28
|
+
### 개선
|
|
29
|
+
|
|
30
|
+
- Sidebar 외형: 기본 `default`(우측 보더만) / `wrapper`(패딩·radius·보더 카드형), 외형별 접힌 폭(default 64px · wrapper 80px)
|
|
31
|
+
- SegmentControl · SearchBar 기본 radius를 입력 필드처럼 사이즈별로 적용, pill은 명시적 옵션으로 분리
|
|
32
|
+
- SearchBar 드롭다운 radius 및 드롭다운 열림 시 컨테이너 radius 유지
|
|
33
|
+
- RangeSlider 레이블·마커 간격 축소, 마커 폰트 크기를 사이즈(s·m·l)에 맞춰 조정
|
|
34
|
+
- Tabs full-width에서 리사이즈 시 인디케이터 위치·폭 재계산(ResizeObserver)
|
|
35
|
+
- ui-wc SCSS를 `packages/ui`와 분리해 독립 관리(자동 동기화 스크립트 제거)
|
|
36
|
+
|
|
37
|
+
### 수정
|
|
38
|
+
|
|
39
|
+
- SegmentControl 탭 전환 시 인디케이터가 이전 위치에서 튀는 문제
|
|
40
|
+
- FloatingActionButton 로딩 상태에서 스피너가 보이지 않던 문제
|
|
41
|
+
|
|
3
42
|
## 0.7.1 - 2026-07-18
|
|
4
43
|
|
|
5
44
|
### 추가
|
package/README.md
CHANGED
|
@@ -4,6 +4,15 @@ Designbase **Web Components** — Vue 3, Angular, React, vanilla HTML에서 공
|
|
|
4
4
|
|
|
5
5
|
100여 개의 커스텀 엘리먼트를 제공하며, React 전용 wrapper(`@designbasekorea/ui-wc/react`)도 포함합니다.
|
|
6
6
|
|
|
7
|
+
## v0.7.3 업데이트
|
|
8
|
+
|
|
9
|
+
- Sidebar 프롭 정리: `variant`(외형 `default`·`wrapper`) / `theme`(색상 `default`·`dark`·`light`), 외형별 접힌 폭
|
|
10
|
+
- SegmentControl·SearchBar radius를 사이즈별 기본값으로, pill은 `appearance` 옵션으로 분리
|
|
11
|
+
- RangeSlider 레이블·마커 간격 및 사이즈별 마커 폰트 정리
|
|
12
|
+
- Tabs full-width 리사이즈 시 인디케이터 재계산(ResizeObserver)
|
|
13
|
+
- SegmentControl 인디케이터 튐·FloatingActionButton 로딩 스피너 수정
|
|
14
|
+
- ui-wc SCSS 독립 관리로 전환
|
|
15
|
+
|
|
7
16
|
## v0.7.1 업데이트
|
|
8
17
|
|
|
9
18
|
- Sidebar `nav-top` · `nav` · `nav-bottom` 커스텀 내비게이션 슬롯 추가
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{hexToRgb as t,rgbToHsv as e,hsvToRgb as i,toHex as s,rgbToHsl as l,formatColor as n,normalizeHex as o,isHex as a,clamp as r}from"./color-picker-utils.js";import{getDbComponentIconSize as h,createDbIcon as d}from"./db-icons.js";const p=["s","m","l"],u=["dropdown","modal"],c=["bottom-start","bottom-end","top-start","top-end"],g="#006FFF",E=t(g)??{r:0,g:111,b:255},m=e(E.r,E.g,E.b),b=JSON.stringify([{label:"HEX",value:"hex"},{label:"RGB",value:"rgb"},{label:"RGBA",value:"rgba"},{label:"HSL",value:"hsl"},{label:"HSLA",value:"hsla"}]);class DbColorPicker extends HTMLElement{constructor(){super(...arguments),this.h=m.h,this.s=m.s,this.v=m.v,this.a=100,this.open=!1,this.format="hex",this.colorInput=g,this.alphaInput="100",this.isCopied=!1,this.tempColor="",this.dragging=null,this.mounted=!1,this.copiedTimer=null,this.debounceTimer=null,this.lastEmittedHex="",this.suppressNextValueSync=!1,this.didMount=!1,this.triggerInputFocused=!1,this.panelInputFocused=!1,this.panelAlphaInputFocused=!1,this.handleOutsideClick=t=>{if(!this.open||"dropdown"!==this.getOption("type",u,"dropdown"))return;const e=t.target;this.contains(e)||this.formatSelectEl?.contains(e)||(this.open=!1,this.update())},this.handleDocumentMouseMove=t=>{"area"===this.dragging&&(this.getBool("disabled")||this.getBool("readonly")||this.updateFromArea(t.clientX,t.clientY))},this.handleDocumentMouseUp=()=>{"area"===this.dragging&&(this.dragging=null,this.onColorStateChanged(!0))},this.handleModalCancel=()=>{const i=t(this.tempColor);if(i){const t=e(i.r,i.g,i.b);this.h=t.h,this.s=t.s,this.v=t.v}this.open=!1,this.update(),this.dispatchEvent(new CustomEvent("db-cancel",{bubbles:!0,composed:!0}))},this.handleModalApply=()=>{this.open=!1,this.actuallyEmit(),this.dispatchEvent(new CustomEvent("db-apply",{detail:{value:this.getOutward()},bubbles:!0,composed:!0})),this.update()}}static get observedAttributes(){return["size","type","position","value","default-value","show-input","show-alpha","show-format-selector","show-copy-button","show-eyedropper","disabled","readonly","full-width","error","on-change-format","change-debounce-ms","emit-during-drag"]}connectedCallback(){this.mounted||this.mount(),this.syncFromValueAttr(!0),this.update(),document.addEventListener("mousedown",this.handleOutsideClick),document.addEventListener("mousemove",this.handleDocumentMouseMove),document.addEventListener("mouseup",this.handleDocumentMouseUp)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleOutsideClick),document.removeEventListener("mousemove",this.handleDocumentMouseMove),document.removeEventListener("mouseup",this.handleDocumentMouseUp),this.copiedTimer&&clearTimeout(this.copiedTimer),this.debounceTimer&&clearTimeout(this.debounceTimer)}attributeChangedCallback(t){this.mounted&&("value"!==t&&"default-value"!==t||this.syncFromValueAttr(!1),this.update())}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getOption(t,e,i){const s=this.getAttribute(t);return s&&e.includes(s)?s:i}getIconSize(){return h(this.getOption("size",p,"m"))}getRgb(){return i(this.h,this.s,this.v)}getHex(){const t=this.getRgb();return s(t.r,t.g,t.b)}getHsl(){const t=this.getRgb();return l(t.r,t.g,t.b)}getUiFormatted(){const t=this.getRgb(),e=this.getHex(),i=this.getHsl();return n(this.format,t,e,i,this.a)}getOutward(){return"hex"===("ui"===this.getAttribute("on-change-format")?"ui":"hex")?this.getHex():this.getUiFormatted()}syncFromValueAttr(i){const s=this.getAttribute("value")??(i?this.getAttribute("default-value"):null)??(i?g:null);if(null==s)return;const l=o(s);if(!a(l))return;if(!i&&this.suppressNextValueSync&&l===this.lastEmittedHex)return void(this.suppressNextValueSync=!1);const n=t(l);if(!n)return;const r=e(n.r,n.g,n.b);this.h=r.h,this.s=r.s,this.v=r.v,this.colorInput=l,this.lastEmittedHex=l}actuallyEmit(){const t=o(this.getHex()),e=this.hasAttribute("value")&&a(this.getAttribute("value")||"")?o(this.getAttribute("value")||""):null;e&&e===t||this.lastEmittedHex!==t&&(this.lastEmittedHex=t,this.suppressNextValueSync=!0,this.setAttribute("value",t),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.getOutward()},bubbles:!0,composed:!0})))}scheduleEmit(){const t=this.getBool("emit-during-drag",!0);if(this.dragging&&!t)return;const e=Number(this.getAttribute("change-debounce-ms")||"0");if(e>0)return this.debounceTimer&&clearTimeout(this.debounceTimer),void(this.debounceTimer=setTimeout(()=>this.actuallyEmit(),e));this.actuallyEmit()}onColorStateChanged(t=!1){this.didMount?(!t||this.getBool("emit-during-drag",!0),this.scheduleEmit()):this.didMount=!0}updateFromArea(t,e){const i=this.colorFieldEl;if(!i)return;const s=i.getBoundingClientRect(),l=r(t-s.left,0,s.width),n=r(e-s.top,0,s.height);this.s=l/s.width*100,this.v=100-n/s.height*100,this.updateVisuals(),this.onColorStateChanged()}getInputValue(t){return t?t.getAttribute("value")??"":""}setInputValue(t,e){t&&void 0!==e&&t.setAttribute("value",e)}getPanelControlSize(){return"s"===this.getOption("size",p,"m")?"s":"m"}commitColorInput(i){const s=("trigger"===i?this.triggerInputEl?.value:this.getInputValue(this.panelValueInputEl)??"").trim();if(/^#([0-9A-Fa-f]{6})$/.test(s)){const i=t(s),l=e(i.r,i.g,i.b);return this.h=l.h,this.s=l.s,this.v=l.v,this.colorInput=o(s),this.updateVisuals(),void this.onColorStateChanged()}let l=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(s);if(l){const t=r(parseInt(l[1],10),0,255),i=r(parseInt(l[2],10),0,255),s=r(parseInt(l[3],10),0,255),n=e(t,i,s);return this.h=n.h,this.s=n.s,this.v=n.v,this.colorInput=`rgb(${t}, ${i}, ${s})`,this.updateVisuals(),void this.onColorStateChanged()}if(l=/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)$/i.exec(s),l){const t=r(parseInt(l[1],10),0,255),i=r(parseInt(l[2],10),0,255),s=r(parseInt(l[3],10),0,255),n=parseFloat(l[4]),o=e(t,i,s);this.h=o.h,this.s=o.s,this.v=o.v,this.a=Math.round(100*n),this.alphaInput=String(this.a),this.colorInput=`rgba(${t}, ${i}, ${s}, ${n})`,this.updateVisuals(),this.onColorStateChanged()}}commitAlphaInput(){const t=Number(this.getInputValue(this.panelAlphaInputEl).trim()||this.alphaInput);if(!Number.isNaN(t)&&t>=0&&t<=100){const e=Math.round(t);this.a=e,this.alphaInput=String(e),this.updateVisuals(),this.onColorStateChanged()}else this.alphaInput=String(this.a),this.panelAlphaInputEl&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput)}async onCopy(){try{await navigator.clipboard.writeText(this.getUiFormatted()),this.isCopied=!0,this.updateCopyButtons(),this.copiedTimer&&clearTimeout(this.copiedTimer),this.copiedTimer=setTimeout(()=>{this.isCopied=!1,this.updateCopyButtons()},1600)}catch{}}async onEyedrop(){try{if("EyeDropper"in window){const i=new window.EyeDropper,{sRGBHex:s}=await i.open(),l=t(s);if(!l)return;const n=e(l.r,l.g,l.b);this.h=n.h,this.s=n.s,this.v=n.v,this.updateVisuals(),this.onColorStateChanged()}}catch{}}toggleOpen(){if(this.getBool("disabled")||this.getBool("readonly"))return;if("modal"===this.getOption("type",u,"dropdown"))return this.tempColor=this.getHex(),this.open=!0,void this.update();this.open=!this.open,this.update()}mount(){this.mounted=!0;const t=this.getIconSize();this.triggerEl=document.createElement("div"),this.triggerEl.className="designbase-wc-color-picker__trigger",this.triggerEl.addEventListener("click",()=>this.toggleOpen());const e=document.createElement("div");e.className="designbase-wc-color-picker__color-display",this.colorBoxEl=document.createElement("div"),this.colorBoxEl.className="designbase-wc-color-picker__color-box",e.append(this.colorBoxEl),this.triggerInputEl=document.createElement("input"),this.triggerInputEl.type="text",this.triggerInputEl.className="designbase-wc-color-picker__input",this.triggerInputEl.placeholder="#000000",this.triggerInputEl.addEventListener("click",t=>t.stopPropagation()),this.triggerInputEl.addEventListener("focus",()=>{this.triggerInputFocused=!0}),this.triggerInputEl.addEventListener("blur",()=>{this.triggerInputFocused=!1;const t="hex"===this.format?o(this.getUiFormatted()):this.getUiFormatted();this.triggerInputEl&&this.triggerInputEl.value!==t&&(this.triggerInputEl.value=t,this.colorInput=t)}),this.triggerInputEl.addEventListener("input",()=>{this.triggerInputEl&&(this.colorInput=this.triggerInputEl.value)}),this.triggerInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitColorInput("trigger")});const i=document.createElement("div");i.className="designbase-wc-color-picker__trigger-actions",this.triggerCopyBtn=document.createElement("button"),this.triggerCopyBtn.type="button",this.triggerCopyBtn.className="designbase-wc-color-picker__copy-button-inline",this.triggerCopyBtn.setAttribute("aria-label","Copy color value"),this.triggerCopyBtn.addEventListener("click",t=>{t.stopPropagation(),this.onCopy()}),this.toggleBtn=document.createElement("button"),this.toggleBtn.type="button",this.toggleBtn.className="designbase-wc-color-picker__toggle",this.toggleBtn.setAttribute("aria-label","Toggle color picker"),this.toggleBtn.append(d("chevron-down",t)),i.append(this.triggerCopyBtn,this.toggleBtn),this.triggerEl.append(e,this.triggerInputEl,i),this.dropdownEl=document.createElement("div"),this.dropdownEl.className="designbase-wc-color-picker__dropdown",this.dropdownEl.addEventListener("click",t=>t.stopPropagation()),this.dropdownEl.hidden=!0;const s=document.createElement("div");s.className="designbase-wc-color-picker__selector";const l=document.createElement("div");l.className="designbase-wc-color-picker__color-area",this.colorFieldEl=document.createElement("div"),this.colorFieldEl.className="designbase-wc-color-picker__color-field",this.colorPointerEl=document.createElement("div"),this.colorPointerEl.className="designbase-wc-color-picker__color-pointer",this.colorFieldEl.append(this.colorPointerEl),this.colorFieldEl.addEventListener("mousedown",t=>{this.getBool("disabled")||this.getBool("readonly")||(t.preventDefault(),this.dragging="area",this.updateFromArea(t.clientX,t.clientY))}),this.colorFieldEl.addEventListener("touchstart",t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;this.dragging="area";const e=t.touches[0];this.updateFromArea(e.clientX,e.clientY)},{passive:!0}),this.colorFieldEl.addEventListener("touchmove",t=>{if("area"!==this.dragging)return;const e=t.touches[0];this.updateFromArea(e.clientX,e.clientY)},{passive:!0}),this.colorFieldEl.addEventListener("touchend",()=>{"area"===this.dragging&&(this.dragging=null,this.onColorStateChanged(!0))}),l.append(this.colorFieldEl);const n=document.createElement("div");n.className="designbase-wc-color-picker__controls",this.eyedropperBtnEl=document.createElement("db-button"),this.eyedropperBtnEl.setAttribute("variant","tertiary"),this.eyedropperBtnEl.setAttribute("size",this.getPanelControlSize()),this.eyedropperBtnEl.setAttribute("icon-only",""),this.eyedropperBtnEl.setAttribute("start-icon","eyedropper"),this.eyedropperBtnEl.setAttribute("aria-label","Eyedropper tool"),this.eyedropperBtnEl.addEventListener("click",()=>{this.onEyedrop()});const a=document.createElement("div");a.className="designbase-wc-color-picker__slider-container";const h=document.createElement("div");h.className="designbase-wc-color-picker__hue-slider",this.hueSliderEl=document.createElement("input"),this.hueSliderEl.type="range",this.hueSliderEl.min="0",this.hueSliderEl.max="360",this.hueSliderEl.className="designbase-wc-color-picker__slider designbase-wc-color-picker__slider--hue",this.hueSliderEl.addEventListener("input",()=>{this.h=parseFloat(this.hueSliderEl.value),this.updateVisuals(),this.onColorStateChanged()}),h.append(this.hueSliderEl),this.alphaSliderWrapEl=document.createElement("div"),this.alphaSliderWrapEl.className="designbase-wc-color-picker__alpha-slider",this.alphaSliderEl=document.createElement("input"),this.alphaSliderEl.type="range",this.alphaSliderEl.min="0",this.alphaSliderEl.max="100",this.alphaSliderEl.className="designbase-wc-color-picker__slider designbase-wc-color-picker__slider--alpha",this.alphaSliderEl.addEventListener("input",()=>{this.a=r(parseInt(this.alphaSliderEl.value,10),0,100),this.alphaInput=String(this.a),this.panelAlphaInputEl&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput),this.updateVisuals(),this.onColorStateChanged()}),this.alphaSliderWrapEl.append(this.alphaSliderEl),a.append(h,this.alphaSliderWrapEl),n.append(this.eyedropperBtnEl,a);const p=document.createElement("div");p.className="designbase-wc-color-picker__value-display",this.formatSelectEl=document.createElement("db-select"),this.formatSelectEl.setAttribute("size","s"),this.formatSelectEl.setAttribute("position","top"),this.formatSelectEl.setAttribute("show-clear-button","false"),this.formatSelectEl.setAttribute("options",b),this.formatSelectEl.addEventListener("db-change",t=>{const e=t.detail,i=e?.value;i&&(this.format=i,this.updateVisuals())}),this.panelValueInputEl=document.createElement("db-input"),this.panelValueInputEl.classList.add("designbase-wc-color-picker__value-input"),this.panelValueInputEl.setAttribute("size","s"),this.panelValueInputEl.setAttribute("placeholder","#000000"),this.panelValueInputEl.addEventListener("db-focus",()=>{this.panelInputFocused=!0}),this.panelValueInputEl.addEventListener("db-blur",()=>{this.panelInputFocused=!1;const t="hex"===this.format?o(this.getUiFormatted()):this.getUiFormatted();this.getInputValue(this.panelValueInputEl)!==t&&(this.setInputValue(this.panelValueInputEl,t),this.colorInput=t)}),this.panelValueInputEl.addEventListener("db-input",t=>{const e=t.detail;void 0!==e?.value&&(this.colorInput=e.value)}),this.panelValueInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitColorInput("panel")}),this.panelAlphaWrapEl=document.createElement("div"),this.panelAlphaWrapEl.className="designbase-wc-color-picker__alpha-input-wrap",this.panelAlphaInputEl=document.createElement("db-input"),this.panelAlphaInputEl.classList.add("designbase-wc-color-picker__alpha-input"),this.panelAlphaInputEl.setAttribute("size","s"),this.panelAlphaInputEl.setAttribute("placeholder","100"),this.panelAlphaInputEl.setAttribute("aria-label","Alpha percent"),this.panelAlphaInputEl.addEventListener("db-focus",()=>{this.panelAlphaInputFocused=!0}),this.panelAlphaInputEl.addEventListener("db-blur",()=>{this.panelAlphaInputFocused=!1,this.commitAlphaInput()}),this.panelAlphaInputEl.addEventListener("db-input",t=>{const e=t.detail,i=(e?.value??"").replace(/[^\d]/g,"").slice(0,3);i!==e?.value&&this.setInputValue(this.panelAlphaInputEl,i),this.alphaInput=i}),this.panelAlphaInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitAlphaInput()});const u=document.createElement("span");u.className="designbase-wc-color-picker__alpha-suffix",u.textContent="%",this.panelAlphaWrapEl.append(this.panelAlphaInputEl,u),this.panelCopyBtnEl=document.createElement("db-button"),this.panelCopyBtnEl.setAttribute("variant","tertiary"),this.panelCopyBtnEl.setAttribute("size","s"),this.panelCopyBtnEl.setAttribute("icon-only",""),this.panelCopyBtnEl.setAttribute("start-icon","copy"),this.panelCopyBtnEl.setAttribute("aria-label","Copy color value"),this.panelCopyBtnEl.addEventListener("click",()=>{this.onCopy()}),p.append(this.formatSelectEl,this.panelValueInputEl,this.panelAlphaWrapEl,this.panelCopyBtnEl),s.append(l,n,p),this.selectorEl=s,this.dropdownEl.append(s),this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","s"),this.modalEl.setAttribute("title","색상 선택"),this.modalEl.setAttribute("close-on-escape","true"),this.modalEl.addEventListener("db-close",this.handleModalCancel),this.modalBodyEl=document.createElement("div"),this.modalBodyEl.setAttribute("data-modal-part","body");const c=document.createElement("div");c.setAttribute("data-modal-part","footer"),c.style.display="flex",c.style.gap="8px",c.style.justifyContent="flex-end";const g=document.createElement("db-button");g.setAttribute("variant","tertiary"),g.setAttribute("size","m"),g.textContent="취소",g.addEventListener("click",this.handleModalCancel);const E=document.createElement("db-button");E.setAttribute("variant","primary"),E.setAttribute("size","m"),E.textContent="적용",E.addEventListener("click",this.handleModalApply),c.append(g,E),this.modalEl.append(this.modalBodyEl,c),this.replaceChildren(this.triggerEl,this.dropdownEl,this.modalEl)}updateCopyButtons(){const t=this.getIconSize(),e=this.isCopied?"done":"copy";this.triggerCopyBtn&&this.triggerCopyBtn.replaceChildren(d(e,t)),this.panelCopyBtnEl&&this.panelCopyBtnEl.setAttribute("start-icon",e)}updateVisuals(){const t=this.getRgb(),e=this.getHex(),i=this.getBool("show-alpha",!0),s=this.getUiFormatted(),l="hex"===this.format?o(s):s;!this.triggerInputFocused&&this.triggerInputEl&&(this.triggerInputEl.value=l),!this.panelInputFocused&&this.panelValueInputEl&&this.setInputValue(this.panelValueInputEl,l),this.colorBoxEl&&(this.colorBoxEl.style.backgroundColor=i?`rgba(${t.r}, ${t.g}, ${t.b}, ${this.a/100})`:e),this.colorFieldEl&&(this.colorFieldEl.style.backgroundImage=`\n linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)),\n linear-gradient(to right, #ffffff, hsl(${this.h}, 100%, 50%))\n `),this.colorPointerEl&&(this.colorPointerEl.style.left=`${this.s}%`,this.colorPointerEl.style.top=100-this.v+"%",this.colorPointerEl.style.backgroundColor=`rgb(${t.r}, ${t.g}, ${t.b})`),this.hueSliderEl&&(this.hueSliderEl.value=String(this.h),this.hueSliderEl.style.background="linear-gradient(to right,\n hsl(0,100%,50%),\n hsl(60,100%,50%),\n hsl(120,100%,50%),\n hsl(180,100%,50%),\n hsl(240,100%,50%),\n hsl(300,100%,50%),\n hsl(360,100%,50%))"),this.alphaSliderEl&&(this.alphaSliderEl.value=String(this.a),this.alphaSliderEl.style.backgroundImage=`\n linear-gradient(45deg, var(--db-border-base) 25%, transparent 25%),\n linear-gradient(-45deg, var(--db-border-base) 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, var(--db-border-base) 75%),\n linear-gradient(-45deg, transparent 75%, var(--db-border-base) 75%),\n linear-gradient(to right, rgba(${t.r}, ${t.g}, ${t.b}, 0), rgba(${t.r}, ${t.g}, ${t.b}, 1))\n `,this.alphaSliderEl.style.backgroundSize="8px 8px,8px 8px,8px 8px,8px 8px,100% 100%",this.alphaSliderEl.style.backgroundPosition="0 0,0 4px,4px -4px,-4px 0,0 0",this.alphaSliderEl.style.backgroundColor="var(--db-surface-base)"),this.panelAlphaInputEl&&!this.panelAlphaInputFocused&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput),this.formatSelectEl&&this.formatSelectEl.getAttribute("value")!==this.format&&this.formatSelectEl.setAttribute("value",this.format),this.colorInput=l}update(){if(!this.mounted)return;const t=this.getOption("size",p,"m"),e=this.getOption("type",u,"dropdown"),i=this.getOption("position",c,"bottom-start"),s=this.getBool("disabled"),l=this.getBool("readonly"),n=this.getBool("show-input",!0),o=this.getBool("show-alpha",!0),a=this.getBool("show-format-selector",!0),r=this.getBool("show-copy-button",!0),h=this.getBool("show-eyedropper",!0),d="undefined"!=typeof window&&"EyeDropper"in window;if(this.className=["designbase-wc-color-picker",`designbase-wc-color-picker--${t}`,`designbase-wc-color-picker--${i}`,this.open&&"dropdown"===e&&"designbase-wc-color-picker--open",this.getBool("full-width")&&"designbase-wc-color-picker--full-width",this.getBool("error")&&"designbase-wc-color-picker--error",s&&"designbase-wc-color-picker--disabled",l&&"designbase-wc-color-picker--readonly",!n&&"designbase-wc-color-picker--no-input"].filter(Boolean).join(" "),this.triggerInputEl&&(this.triggerInputEl.hidden=!n,this.triggerInputEl.disabled=s,this.triggerInputEl.readOnly=l),this.triggerCopyBtn&&(this.triggerCopyBtn.hidden=!(n&&r),this.triggerCopyBtn.disabled=s),this.toggleBtn&&(this.toggleBtn.disabled=s),this.dropdownEl&&(this.dropdownEl.className=`designbase-wc-color-picker__dropdown designbase-wc-color-picker__dropdown--${i}`,this.dropdownEl.hidden=!("dropdown"===e&&this.open)),this.alphaSliderWrapEl&&(this.alphaSliderWrapEl.hidden=!o),this.panelAlphaWrapEl&&(this.panelAlphaWrapEl.hidden=!o),this.formatSelectEl&&(this.formatSelectEl.hidden=!a),this.panelCopyBtnEl&&(this.panelCopyBtnEl.hidden=!r),this.eyedropperBtnEl&&(this.eyedropperBtnEl.hidden=!(h&&d)),this.selectorEl){const t="modal"===e?this.modalBodyEl:this.dropdownEl;t&&this.selectorEl.parentElement!==t&&t.append(this.selectorEl)}this.modalEl&&("modal"===e&&this.open?this.modalEl.setAttribute("open","true"):this.modalEl.removeAttribute("open")),this.updateCopyButtons(),this.updateVisuals()}}customElements.get("db-color-picker")||customElements.define("db-color-picker",DbColorPicker);export{DbColorPicker};
|
|
1
|
+
import{hexToRgb as t,rgbToHsv as e,hsvToRgb as i,toHex as s,rgbToHsl as l,formatColor as n,normalizeHex as o,isHex as a,clamp as r}from"./color-picker-utils.js";import{getDbComponentIconSize as h,createDbIcon as d}from"./db-icons.js";const p=["s","m","l"],u=["dropdown","modal"],c=["input","swatch"],g=["bottom-start","bottom-end","top-start","top-end"],E="#006FFF",m=t(E)??{r:0,g:111,b:255},b=e(m.r,m.g,m.b),v=JSON.stringify([{label:"HEX",value:"hex"},{label:"RGB",value:"rgb"},{label:"RGBA",value:"rgba"},{label:"HSL",value:"hsl"},{label:"HSLA",value:"hsla"}]);class DbColorPicker extends HTMLElement{constructor(){super(...arguments),this.h=b.h,this.s=b.s,this.v=b.v,this.a=100,this.open=!1,this.format="hex",this.colorInput=E,this.alphaInput="100",this.isCopied=!1,this.tempColor="",this.dragging=null,this.mounted=!1,this.copiedTimer=null,this.debounceTimer=null,this.lastEmittedHex="",this.suppressNextValueSync=!1,this.didMount=!1,this.triggerInputFocused=!1,this.panelInputFocused=!1,this.panelAlphaInputFocused=!1,this.handleOutsideClick=t=>{if(!this.open||"dropdown"!==this.getOption("type",u,"dropdown"))return;const e=t.target;this.contains(e)||this.formatSelectEl?.contains(e)||(this.open=!1,this.update())},this.handleDocumentMouseMove=t=>{"area"===this.dragging&&(this.getBool("disabled")||this.getBool("readonly")||this.updateFromArea(t.clientX,t.clientY))},this.handleDocumentMouseUp=()=>{"area"===this.dragging&&(this.dragging=null,this.onColorStateChanged(!0))},this.handleModalCancel=()=>{const i=t(this.tempColor);if(i){const t=e(i.r,i.g,i.b);this.h=t.h,this.s=t.s,this.v=t.v}this.open=!1,this.update(),this.dispatchEvent(new CustomEvent("db-cancel",{bubbles:!0,composed:!0}))},this.handleModalApply=()=>{this.open=!1,this.actuallyEmit(),this.dispatchEvent(new CustomEvent("db-apply",{detail:{value:this.getOutward()},bubbles:!0,composed:!0})),this.update()}}static get observedAttributes(){return["size","type","trigger","position","value","default-value","show-input","show-alpha","show-format-selector","show-copy-button","show-eyedropper","disabled","readonly","full-width","error","on-change-format","change-debounce-ms","emit-during-drag"]}connectedCallback(){this.mounted||this.mount(),this.syncFromValueAttr(!0),this.update(),document.addEventListener("mousedown",this.handleOutsideClick),document.addEventListener("mousemove",this.handleDocumentMouseMove),document.addEventListener("mouseup",this.handleDocumentMouseUp)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleOutsideClick),document.removeEventListener("mousemove",this.handleDocumentMouseMove),document.removeEventListener("mouseup",this.handleDocumentMouseUp),this.copiedTimer&&clearTimeout(this.copiedTimer),this.debounceTimer&&clearTimeout(this.debounceTimer)}attributeChangedCallback(t){this.mounted&&("value"!==t&&"default-value"!==t||this.syncFromValueAttr(!1),this.update())}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getOption(t,e,i){const s=this.getAttribute(t);return s&&e.includes(s)?s:i}getIconSize(){return h(this.getOption("size",p,"m"))}getRgb(){return i(this.h,this.s,this.v)}getHex(){const t=this.getRgb();return s(t.r,t.g,t.b)}getHsl(){const t=this.getRgb();return l(t.r,t.g,t.b)}getUiFormatted(){const t=this.getRgb(),e=this.getHex(),i=this.getHsl();return n(this.format,t,e,i,this.a)}getOutward(){return"hex"===("ui"===this.getAttribute("on-change-format")?"ui":"hex")?this.getHex():this.getUiFormatted()}syncFromValueAttr(i){const s=this.getAttribute("value")??(i?this.getAttribute("default-value"):null)??(i?E:null);if(null==s)return;const l=o(s);if(!a(l))return;if(!i&&this.suppressNextValueSync&&l===this.lastEmittedHex)return void(this.suppressNextValueSync=!1);const n=t(l);if(!n)return;const r=e(n.r,n.g,n.b);this.h=r.h,this.s=r.s,this.v=r.v,this.colorInput=l,this.lastEmittedHex=l}actuallyEmit(){const t=o(this.getHex()),e=this.hasAttribute("value")&&a(this.getAttribute("value")||"")?o(this.getAttribute("value")||""):null;e&&e===t||this.lastEmittedHex!==t&&(this.lastEmittedHex=t,this.suppressNextValueSync=!0,this.setAttribute("value",t),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.getOutward()},bubbles:!0,composed:!0})))}scheduleEmit(){const t=this.getBool("emit-during-drag",!0);if(this.dragging&&!t)return;const e=Number(this.getAttribute("change-debounce-ms")||"0");if(e>0)return this.debounceTimer&&clearTimeout(this.debounceTimer),void(this.debounceTimer=setTimeout(()=>this.actuallyEmit(),e));this.actuallyEmit()}onColorStateChanged(t=!1){this.didMount?(!t||this.getBool("emit-during-drag",!0),this.scheduleEmit()):this.didMount=!0}updateFromArea(t,e){const i=this.colorFieldEl;if(!i)return;const s=i.getBoundingClientRect(),l=r(t-s.left,0,s.width),n=r(e-s.top,0,s.height);this.s=l/s.width*100,this.v=100-n/s.height*100,this.updateVisuals(),this.onColorStateChanged()}getInputValue(t){return t?t.getAttribute("value")??"":""}setInputValue(t,e){t&&void 0!==e&&t.setAttribute("value",e)}getPanelControlSize(){return"s"===this.getOption("size",p,"m")?"s":"m"}commitColorInput(i){const s=("trigger"===i?this.triggerInputEl?.value:this.getInputValue(this.panelValueInputEl)??"").trim();if(/^#([0-9A-Fa-f]{6})$/.test(s)){const i=t(s),l=e(i.r,i.g,i.b);return this.h=l.h,this.s=l.s,this.v=l.v,this.colorInput=o(s),this.updateVisuals(),void this.onColorStateChanged()}let l=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(s);if(l){const t=r(parseInt(l[1],10),0,255),i=r(parseInt(l[2],10),0,255),s=r(parseInt(l[3],10),0,255),n=e(t,i,s);return this.h=n.h,this.s=n.s,this.v=n.v,this.colorInput=`rgb(${t}, ${i}, ${s})`,this.updateVisuals(),void this.onColorStateChanged()}if(l=/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)$/i.exec(s),l){const t=r(parseInt(l[1],10),0,255),i=r(parseInt(l[2],10),0,255),s=r(parseInt(l[3],10),0,255),n=parseFloat(l[4]),o=e(t,i,s);this.h=o.h,this.s=o.s,this.v=o.v,this.a=Math.round(100*n),this.alphaInput=String(this.a),this.colorInput=`rgba(${t}, ${i}, ${s}, ${n})`,this.updateVisuals(),this.onColorStateChanged()}}commitAlphaInput(){const t=Number(this.getInputValue(this.panelAlphaInputEl).trim()||this.alphaInput);if(!Number.isNaN(t)&&t>=0&&t<=100){const e=Math.round(t);this.a=e,this.alphaInput=String(e),this.updateVisuals(),this.onColorStateChanged()}else this.alphaInput=String(this.a),this.panelAlphaInputEl&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput)}async onCopy(){try{await navigator.clipboard.writeText(this.getUiFormatted()),this.isCopied=!0,this.updateCopyButtons(),this.copiedTimer&&clearTimeout(this.copiedTimer),this.copiedTimer=setTimeout(()=>{this.isCopied=!1,this.updateCopyButtons()},1600)}catch{}}async onEyedrop(){try{if("EyeDropper"in window){const i=new window.EyeDropper,{sRGBHex:s}=await i.open(),l=t(s);if(!l)return;const n=e(l.r,l.g,l.b);this.h=n.h,this.s=n.s,this.v=n.v,this.updateVisuals(),this.onColorStateChanged()}}catch{}}toggleOpen(){if(this.getBool("disabled")||this.getBool("readonly"))return;if("modal"===this.getOption("type",u,"dropdown"))return this.tempColor=this.getHex(),this.open=!0,void this.update();this.open=!this.open,this.update()}close(){this.open&&"dropdown"===this.getOption("type",u,"dropdown")&&(this.open=!1,this.update())}mount(){this.mounted=!0;const t=this.getIconSize();this.triggerEl=document.createElement("div"),this.triggerEl.className="designbase-wc-color-picker__trigger",this.triggerEl.addEventListener("click",()=>this.toggleOpen());const e=document.createElement("div");e.className="designbase-wc-color-picker__color-display",this.colorBoxEl=document.createElement("div"),this.colorBoxEl.className="designbase-wc-color-picker__color-box",e.append(this.colorBoxEl),this.triggerInputEl=document.createElement("input"),this.triggerInputEl.type="text",this.triggerInputEl.className="designbase-wc-color-picker__input",this.triggerInputEl.placeholder="#000000",this.triggerInputEl.addEventListener("click",t=>t.stopPropagation()),this.triggerInputEl.addEventListener("focus",()=>{this.triggerInputFocused=!0}),this.triggerInputEl.addEventListener("blur",()=>{this.triggerInputFocused=!1;const t="hex"===this.format?o(this.getUiFormatted()):this.getUiFormatted();this.triggerInputEl&&this.triggerInputEl.value!==t&&(this.triggerInputEl.value=t,this.colorInput=t)}),this.triggerInputEl.addEventListener("input",()=>{this.triggerInputEl&&(this.colorInput=this.triggerInputEl.value)}),this.triggerInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitColorInput("trigger")});const i=document.createElement("div");i.className="designbase-wc-color-picker__trigger-actions",this.triggerCopyBtn=document.createElement("button"),this.triggerCopyBtn.type="button",this.triggerCopyBtn.className="designbase-wc-color-picker__copy-button-inline",this.triggerCopyBtn.setAttribute("aria-label","Copy color value"),this.triggerCopyBtn.addEventListener("click",t=>{t.stopPropagation(),this.onCopy()}),this.toggleBtn=document.createElement("button"),this.toggleBtn.type="button",this.toggleBtn.className="designbase-wc-color-picker__toggle",this.toggleBtn.setAttribute("aria-label","Toggle color picker"),this.toggleBtn.append(d("chevron-down",t)),i.append(this.triggerCopyBtn,this.toggleBtn),this.triggerEl.append(e,this.triggerInputEl,i),this.dropdownEl=document.createElement("div"),this.dropdownEl.className="designbase-wc-color-picker__dropdown",this.dropdownEl.addEventListener("click",t=>t.stopPropagation()),this.dropdownEl.hidden=!0;const s=document.createElement("div");s.className="designbase-wc-color-picker__selector";const l=document.createElement("div");l.className="designbase-wc-color-picker__color-area",this.colorFieldEl=document.createElement("div"),this.colorFieldEl.className="designbase-wc-color-picker__color-field",this.colorPointerEl=document.createElement("div"),this.colorPointerEl.className="designbase-wc-color-picker__color-pointer",this.colorFieldEl.append(this.colorPointerEl),this.colorFieldEl.addEventListener("mousedown",t=>{this.getBool("disabled")||this.getBool("readonly")||(t.preventDefault(),this.dragging="area",this.updateFromArea(t.clientX,t.clientY))}),this.colorFieldEl.addEventListener("touchstart",t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;this.dragging="area";const e=t.touches[0];this.updateFromArea(e.clientX,e.clientY)},{passive:!0}),this.colorFieldEl.addEventListener("touchmove",t=>{if("area"!==this.dragging)return;const e=t.touches[0];this.updateFromArea(e.clientX,e.clientY)},{passive:!0}),this.colorFieldEl.addEventListener("touchend",()=>{"area"===this.dragging&&(this.dragging=null,this.onColorStateChanged(!0))}),l.append(this.colorFieldEl);const n=document.createElement("div");n.className="designbase-wc-color-picker__controls",this.eyedropperBtnEl=document.createElement("db-button"),this.eyedropperBtnEl.setAttribute("variant","tertiary"),this.eyedropperBtnEl.setAttribute("size",this.getPanelControlSize()),this.eyedropperBtnEl.setAttribute("icon-only",""),this.eyedropperBtnEl.setAttribute("start-icon","eyedropper"),this.eyedropperBtnEl.setAttribute("aria-label","Eyedropper tool"),this.eyedropperBtnEl.addEventListener("click",()=>{this.onEyedrop()});const a=document.createElement("div");a.className="designbase-wc-color-picker__slider-container";const h=document.createElement("div");h.className="designbase-wc-color-picker__hue-slider",this.hueSliderEl=document.createElement("input"),this.hueSliderEl.type="range",this.hueSliderEl.min="0",this.hueSliderEl.max="360",this.hueSliderEl.className="designbase-wc-color-picker__slider designbase-wc-color-picker__slider--hue",this.hueSliderEl.addEventListener("input",()=>{this.h=parseFloat(this.hueSliderEl.value),this.updateVisuals(),this.onColorStateChanged()}),h.append(this.hueSliderEl),this.alphaSliderWrapEl=document.createElement("div"),this.alphaSliderWrapEl.className="designbase-wc-color-picker__alpha-slider",this.alphaSliderEl=document.createElement("input"),this.alphaSliderEl.type="range",this.alphaSliderEl.min="0",this.alphaSliderEl.max="100",this.alphaSliderEl.className="designbase-wc-color-picker__slider designbase-wc-color-picker__slider--alpha",this.alphaSliderEl.addEventListener("input",()=>{this.a=r(parseInt(this.alphaSliderEl.value,10),0,100),this.alphaInput=String(this.a),this.panelAlphaInputEl&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput),this.updateVisuals(),this.onColorStateChanged()}),this.alphaSliderWrapEl.append(this.alphaSliderEl),a.append(h,this.alphaSliderWrapEl),n.append(this.eyedropperBtnEl,a);const p=document.createElement("div");p.className="designbase-wc-color-picker__value-display",this.formatSelectEl=document.createElement("db-select"),this.formatSelectEl.setAttribute("size","s"),this.formatSelectEl.setAttribute("position","top"),this.formatSelectEl.setAttribute("show-clear-button","false"),this.formatSelectEl.setAttribute("options",v),this.formatSelectEl.addEventListener("db-change",t=>{const e=t.detail,i=e?.value;i&&(this.format=i,this.updateVisuals())}),this.panelValueInputEl=document.createElement("db-input"),this.panelValueInputEl.classList.add("designbase-wc-color-picker__value-input"),this.panelValueInputEl.setAttribute("size","s"),this.panelValueInputEl.setAttribute("placeholder","#000000"),this.panelValueInputEl.addEventListener("db-focus",()=>{this.panelInputFocused=!0}),this.panelValueInputEl.addEventListener("db-blur",()=>{this.panelInputFocused=!1;const t="hex"===this.format?o(this.getUiFormatted()):this.getUiFormatted();this.getInputValue(this.panelValueInputEl)!==t&&(this.setInputValue(this.panelValueInputEl,t),this.colorInput=t)}),this.panelValueInputEl.addEventListener("db-input",t=>{const e=t.detail;void 0!==e?.value&&(this.colorInput=e.value)}),this.panelValueInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitColorInput("panel")}),this.panelAlphaWrapEl=document.createElement("div"),this.panelAlphaWrapEl.className="designbase-wc-color-picker__alpha-input-wrap",this.panelAlphaInputEl=document.createElement("db-input"),this.panelAlphaInputEl.classList.add("designbase-wc-color-picker__alpha-input"),this.panelAlphaInputEl.setAttribute("size","s"),this.panelAlphaInputEl.setAttribute("placeholder","100"),this.panelAlphaInputEl.setAttribute("aria-label","Alpha percent"),this.panelAlphaInputEl.addEventListener("db-focus",()=>{this.panelAlphaInputFocused=!0}),this.panelAlphaInputEl.addEventListener("db-blur",()=>{this.panelAlphaInputFocused=!1,this.commitAlphaInput()}),this.panelAlphaInputEl.addEventListener("db-input",t=>{const e=t.detail,i=(e?.value??"").replace(/[^\d]/g,"").slice(0,3);i!==e?.value&&this.setInputValue(this.panelAlphaInputEl,i),this.alphaInput=i}),this.panelAlphaInputEl.addEventListener("keydown",t=>{"Enter"===t.key&&this.commitAlphaInput()});const u=document.createElement("span");u.className="designbase-wc-color-picker__alpha-suffix",u.textContent="%",this.panelAlphaWrapEl.append(this.panelAlphaInputEl,u),this.panelCopyBtnEl=document.createElement("db-button"),this.panelCopyBtnEl.setAttribute("variant","tertiary"),this.panelCopyBtnEl.setAttribute("size","s"),this.panelCopyBtnEl.setAttribute("icon-only",""),this.panelCopyBtnEl.setAttribute("start-icon","copy"),this.panelCopyBtnEl.setAttribute("aria-label","Copy color value"),this.panelCopyBtnEl.addEventListener("click",()=>{this.onCopy()}),p.append(this.formatSelectEl,this.panelValueInputEl,this.panelAlphaWrapEl,this.panelCopyBtnEl),s.append(l,n,p),this.selectorEl=s,this.dropdownEl.append(s),this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","s"),this.modalEl.setAttribute("title","색상 선택"),this.modalEl.setAttribute("close-on-escape","true"),this.modalEl.addEventListener("db-close",this.handleModalCancel),this.modalBodyEl=document.createElement("div"),this.modalBodyEl.className="designbase-wc-modal__body designbase-wc-color-picker__modal-body",this.modalBodyEl.setAttribute("data-modal-part","body");const c=document.createElement("div");c.className="designbase-wc-modal__footer",c.setAttribute("data-modal-part","footer");const g=document.createElement("db-button");g.setAttribute("variant","tertiary"),g.setAttribute("size","m"),g.textContent="취소",g.addEventListener("click",this.handleModalCancel);const E=document.createElement("db-button");E.setAttribute("variant","primary"),E.setAttribute("size","m"),E.textContent="적용",E.addEventListener("click",this.handleModalApply),c.append(g,E),this.modalEl.append(this.modalBodyEl,c),this.replaceChildren(this.triggerEl,this.dropdownEl,this.modalEl)}updateCopyButtons(){const t=this.getIconSize(),e=this.isCopied?"done":"copy";this.triggerCopyBtn&&this.triggerCopyBtn.replaceChildren(d(e,t)),this.panelCopyBtnEl&&this.panelCopyBtnEl.setAttribute("start-icon",e)}updateVisuals(){const t=this.getRgb(),e=this.getHex(),i=this.getBool("show-alpha",!0),s=this.getUiFormatted(),l="hex"===this.format?o(s):s;!this.triggerInputFocused&&this.triggerInputEl&&(this.triggerInputEl.value=l),!this.panelInputFocused&&this.panelValueInputEl&&this.setInputValue(this.panelValueInputEl,l),this.colorBoxEl&&(this.colorBoxEl.style.backgroundColor=i?`rgba(${t.r}, ${t.g}, ${t.b}, ${this.a/100})`:e),this.colorFieldEl&&(this.colorFieldEl.style.backgroundImage=`\n linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)),\n linear-gradient(to right, #ffffff, hsl(${this.h}, 100%, 50%))\n `),this.colorPointerEl&&(this.colorPointerEl.style.left=`${this.s}%`,this.colorPointerEl.style.top=100-this.v+"%",this.colorPointerEl.style.backgroundColor=`rgb(${t.r}, ${t.g}, ${t.b})`),this.hueSliderEl&&(this.hueSliderEl.value=String(this.h),this.hueSliderEl.style.background="linear-gradient(to right,\n hsl(0,100%,50%),\n hsl(60,100%,50%),\n hsl(120,100%,50%),\n hsl(180,100%,50%),\n hsl(240,100%,50%),\n hsl(300,100%,50%),\n hsl(360,100%,50%))"),this.alphaSliderEl&&(this.alphaSliderEl.value=String(this.a),this.alphaSliderEl.style.backgroundImage=`\n linear-gradient(45deg, var(--db-border-base) 25%, transparent 25%),\n linear-gradient(-45deg, var(--db-border-base) 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, var(--db-border-base) 75%),\n linear-gradient(-45deg, transparent 75%, var(--db-border-base) 75%),\n linear-gradient(to right, rgba(${t.r}, ${t.g}, ${t.b}, 0), rgba(${t.r}, ${t.g}, ${t.b}, 1))\n `,this.alphaSliderEl.style.backgroundSize="8px 8px,8px 8px,8px 8px,8px 8px,100% 100%",this.alphaSliderEl.style.backgroundPosition="0 0,0 4px,4px -4px,-4px 0,0 0",this.alphaSliderEl.style.backgroundColor="var(--db-surface-base)"),this.panelAlphaInputEl&&!this.panelAlphaInputFocused&&this.setInputValue(this.panelAlphaInputEl,this.alphaInput),this.formatSelectEl&&this.formatSelectEl.getAttribute("value")!==this.format&&this.formatSelectEl.setAttribute("value",this.format),this.colorInput=l}update(){if(!this.mounted)return;const t=this.getOption("size",p,"m"),e=this.getOption("type",u,"dropdown"),i=this.getOption("position",g,"bottom-start"),s=this.getBool("disabled"),l=this.getBool("readonly"),n=this.getBool("show-input",!0),o=this.getBool("show-alpha",!0),a=this.getBool("show-format-selector",!0),r=this.getBool("show-copy-button",!0),h=this.getBool("show-eyedropper",!0),d="undefined"!=typeof window&&"EyeDropper"in window,E=this.getOption("trigger",c,"input"),m="swatch"===E;if(this.className=["designbase-wc-color-picker",`designbase-wc-color-picker--${t}`,`designbase-wc-color-picker--${i}`,`designbase-wc-color-picker--trigger-${E}`,this.open&&"dropdown"===e&&"designbase-wc-color-picker--open",this.getBool("full-width")&&"designbase-wc-color-picker--full-width",this.getBool("error")&&"designbase-wc-color-picker--error",s&&"designbase-wc-color-picker--disabled",l&&"designbase-wc-color-picker--readonly",!n&&"designbase-wc-color-picker--no-input"].filter(Boolean).join(" "),this.triggerInputEl&&(this.triggerInputEl.hidden=m||!n,this.triggerInputEl.disabled=s,this.triggerInputEl.readOnly=l),this.triggerCopyBtn&&(this.triggerCopyBtn.hidden=m||!(n&&r),this.triggerCopyBtn.disabled=s),this.toggleBtn&&(this.toggleBtn.hidden=m,this.toggleBtn.disabled=s),this.dropdownEl&&(this.dropdownEl.className=`designbase-wc-color-picker__dropdown designbase-wc-color-picker__dropdown--${i}`,this.dropdownEl.hidden=!("dropdown"===e&&this.open)),this.alphaSliderWrapEl&&(this.alphaSliderWrapEl.hidden=!o),this.panelAlphaWrapEl&&(this.panelAlphaWrapEl.hidden=!o),this.formatSelectEl&&(this.formatSelectEl.hidden=!a),this.panelCopyBtnEl&&(this.panelCopyBtnEl.hidden=!r),this.eyedropperBtnEl&&(this.eyedropperBtnEl.hidden=!(h&&d)),this.selectorEl){const t="modal"===e?this.modalBodyEl:this.dropdownEl;t&&this.selectorEl.parentElement!==t&&t.append(this.selectorEl)}this.modalEl&&("modal"===e&&this.open?this.modalEl.setAttribute("open","true"):this.modalEl.removeAttribute("open")),this.updateCopyButtons(),this.updateVisuals()}}customElements.get("db-color-picker")||customElements.define("db-color-picker",DbColorPicker);export{DbColorPicker};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
type DbColorSwatchShape = 'rounded' | 'circle';
|
|
2
|
+
type DbColorSwatchSize = 's' | 'm' | 'l';
|
|
3
|
+
type DbColorSwatchCustomType = 'dropdown' | 'modal';
|
|
4
|
+
type DbColorSwatchItem = {
|
|
5
|
+
value: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
};
|
|
8
|
+
declare class DbColorSwatch extends HTMLElement {
|
|
9
|
+
private colors;
|
|
10
|
+
private selected;
|
|
11
|
+
private customValue;
|
|
12
|
+
private mounted;
|
|
13
|
+
private gridEl?;
|
|
14
|
+
private presetsEl?;
|
|
15
|
+
private customWrapEl?;
|
|
16
|
+
private customTipEl?;
|
|
17
|
+
private customPickerEl?;
|
|
18
|
+
static get observedAttributes(): string[];
|
|
19
|
+
connectedCallback(): void;
|
|
20
|
+
disconnectedCallback(): void;
|
|
21
|
+
private handleOutsideMouseDown;
|
|
22
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
23
|
+
get value(): string;
|
|
24
|
+
set value(next: string);
|
|
25
|
+
private getOption;
|
|
26
|
+
private getBool;
|
|
27
|
+
private parseColors;
|
|
28
|
+
private isCustomSelected;
|
|
29
|
+
private emitChange;
|
|
30
|
+
private selectPreset;
|
|
31
|
+
private render;
|
|
32
|
+
private buildSwatch;
|
|
33
|
+
private ensureCustom;
|
|
34
|
+
private updateCustom;
|
|
35
|
+
}
|
|
36
|
+
declare global {
|
|
37
|
+
interface HTMLElementTagNameMap {
|
|
38
|
+
'db-color-swatch': DbColorSwatch;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { DbColorSwatch };
|
|
43
|
+
export type { DbColorSwatchCustomType, DbColorSwatchItem, DbColorSwatchShape, DbColorSwatchSize };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{normalizeHex as t,isHex as e}from"./color-picker-utils.js";const s=["rounded","circle"],i=["s","m","l"],o=["dropdown","modal"],l=[{value:"#1A1B25",name:"Dark"},{value:"#FFFFFF",name:"White"},{value:"#EF4444",name:"Red"},{value:"#F59E0B",name:"Orange"},{value:"#22C55E",name:"Green"},{value:"#3B82F6",name:"Blue"},{value:"#8B5CF6",name:"Purple"},{value:"#EC4899",name:"Pink"}];class DbColorSwatch extends HTMLElement{constructor(){super(...arguments),this.colors=l,this.selected="",this.customValue="",this.mounted=!1,this.handleOutsideMouseDown=t=>{if(!this.customWrapEl)return;const e=this.customPickerEl;if(!e||"function"!=typeof e.close)return;t.composedPath().includes(this.customWrapEl)||e.close()}}static get observedAttributes(){return["colors","value","default-value","shape","size","show-name","allow-custom","custom-type","disabled"]}connectedCallback(){this.mounted||(this.parseColors(),this.selected=t(this.getAttribute("value")??this.getAttribute("default-value")??""),this.mounted=!0),this.render(),document.addEventListener("mousedown",this.handleOutsideMouseDown,!0)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleOutsideMouseDown,!0)}attributeChangedCallback(e,s,i){this.mounted&&s!==i&&("colors"===e&&this.parseColors(),"value"===e&&(this.selected=t(i??"")),this.render())}get value(){return this.selected}set value(e){this.selected=t(e),this.mounted&&this.render()}getOption(t,e,s){const i=this.getAttribute(t);return i&&e.includes(i)?i:s}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const s=this.getAttribute(t);return""===s||"true"===s}parseColors(){const s=this.getAttribute("colors");if(s)try{const i=JSON.parse(s);if(!Array.isArray(i))return void(this.colors=l);this.colors=i.map(t=>"string"==typeof t?{value:t}:{value:t?.value??"",name:t?.name}).filter(t=>e(t.value)).map(e=>({value:t(e.value),name:e.name})),0===this.colors.length&&(this.colors=l)}catch{this.colors=l}else this.colors=l}isCustomSelected(){if(!this.selected)return!1;return!this.colors.some(t=>t.value.toUpperCase()===this.selected.toUpperCase())}emitChange(t,e){this.dispatchEvent(new CustomEvent("db-change",{detail:{value:t,name:e??""},bubbles:!0,composed:!0}))}selectPreset(t){this.getBool("disabled")||(this.selected=t.value,this.setAttribute("value",this.selected),this.render(),this.emitChange(t.value,t.name))}render(){const t=this.getOption("shape",s,"rounded"),e=this.getOption("size",i,"m"),o=this.getBool("disabled"),l=this.getBool("show-name",!0),c=this.getBool("allow-custom",!0);this.className=["designbase-wc-color-swatch",`designbase-wc-color-swatch--${t}`,`designbase-wc-color-swatch--${e}`,o&&"designbase-wc-color-swatch--disabled"].filter(Boolean).join(" "),this.gridEl||(this.gridEl=document.createElement("div"),this.gridEl.className="designbase-wc-color-swatch__grid",this.presetsEl=document.createElement("div"),this.presetsEl.className="designbase-wc-color-swatch__presets",this.gridEl.append(this.presetsEl)),this.gridEl.parentElement!==this&&this.append(this.gridEl);const a=this.isCustomSelected();this.presetsEl.replaceChildren(...this.colors.map(t=>{const e=!a&&this.selected.toUpperCase()===t.value.toUpperCase();return this.buildSwatch(t,e,l,o)})),c?(this.ensureCustom(),this.updateCustom(e,a,l,o),this.customWrapEl&&this.customWrapEl.parentElement!==this.gridEl&&this.gridEl.append(this.customWrapEl)):this.customWrapEl?.parentElement&&this.customWrapEl.remove()}buildSwatch(t,e,s,i){const o=document.createElement("button");o.type="button",o.className=["designbase-wc-color-swatch__item",e&&"designbase-wc-color-swatch__item--selected"].filter(Boolean).join(" "),o.disabled=i,o.style.setProperty("--db-swatch-color",t.value),o.setAttribute("aria-label",t.name||t.value),o.setAttribute("aria-pressed",String(e));const l=document.createElement("span");if(l.className="designbase-wc-color-swatch__chip",o.append(l),s){const e=document.createElement("span");e.className="designbase-wc-color-swatch__tip",e.textContent=t.name||t.value,o.append(e)}return o.addEventListener("click",()=>this.selectPreset(t)),o}ensureCustom(){this.customWrapEl||(this.customWrapEl=document.createElement("div"),this.customWrapEl.className="designbase-wc-color-swatch__custom",this.customPickerEl=document.createElement("db-color-picker"),this.customPickerEl.setAttribute("trigger","swatch"),this.customPickerEl.setAttribute("show-input","false"),this.customPickerEl.setAttribute("show-copy-button","false"),this.customPickerEl.setAttribute("aria-label","Custom color"),this.customPickerEl.addEventListener("db-change",s=>{s.stopPropagation();const i=s.detail,o=t(i?.value??"");e(o)&&(this.customValue=o,this.selected=o,this.setAttribute("value",o),this.render(),this.emitChange(o,"Custom"))}),this.customTipEl=document.createElement("span"),this.customTipEl.className="designbase-wc-color-swatch__tip",this.customTipEl.textContent="Custom",this.customWrapEl.append(this.customPickerEl,this.customTipEl))}updateCustom(t,e,s,i){this.customWrapEl&&this.customPickerEl&&(this.customWrapEl.classList.toggle("designbase-wc-color-swatch__custom--selected",e),this.customTipEl&&(this.customTipEl.hidden=!s),this.customPickerEl.setAttribute("size",t),this.customPickerEl.setAttribute("type",this.getOption("custom-type",o,"dropdown")),this.customValue&&this.customPickerEl.setAttribute("value",this.customValue),i?this.customPickerEl.setAttribute("disabled",""):this.customPickerEl.removeAttribute("disabled"))}}customElements.get("db-color-swatch")||customElements.define("db-color-swatch",DbColorSwatch);export{DbColorSwatch};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const t="designbase-wc-range-slider";class DbRangeSlider extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.headerEl=null,this.labelEl=null,this.valuesEl=null,this.containerEl=null,this.trackEl=null,this.fillEl=null,this.thumbEls=[],this.currentValue=50,this.currentRange=[25,75],this.isDragging=!1,this.activeThumb=null,this.boundTrackClick=t=>this.handleTrackClick(t),this.boundPointerMove=t=>this.handlePointerMove(t),this.boundPointerUp=()=>this.handlePointerUp(),this.boundContainerKeyDown=t=>this.handleKeyDown(t),this.eventsBound=!1}static get observedAttributes(){return["value","range","min","max","step","size","variant","show-value","show-label","label","value-position","value-fixed","show-thumb-tooltip","show-marks","marks","mark-labels","disabled","readonly","full-width","vertical"]}connectedCallback(){this.built||(this.build(),this.built=!0),this.readAttributeValues(),this.syncClasses(),this.syncDomOrder(),this.syncStructure(),this.syncVisuals(),this.syncA11y(),this.bindEvents()}disconnectedCallback(){this.unbindEvents()}attributeChangedCallback(t){this.built&&(this.readAttributeValues(),this.syncClasses(),this.isStructuralAttribute(t)&&(this.syncDomOrder(),this.syncStructure()),this.syncVisuals(),this.syncA11y())}isStructuralAttribute(t){return["range","show-value","show-label","label","value-position","show-marks","marks","mark-labels","vertical"].includes(t)}get value(){return this.currentValue}set value(t){this.currentValue=this.clamp(t),this.setAttribute("value",String(this.currentValue)),this.syncVisuals()}get range(){if(this.hasAttribute("range"))return[...this.currentRange]}set range(t){if(null==t)return this.removeAttribute("range"),void(this.built&&(this.syncStructure(),this.syncVisuals()));const e=this.normalizeRangeInput(t);if(!e)return;const i=[Math.min(e[0],e[1]),Math.max(e[0],e[1])];this.currentRange=[this.clamp(i[0]),this.clamp(i[1])];const s=`${this.currentRange[0]},${this.currentRange[1]}`;this.getAttribute("range")!==s&&this.setAttribute("range",s),this.built&&this.syncVisuals()}build(){this.classList.add(t),this.headerEl=document.createElement("div"),this.headerEl.className=`${t}__header`,this.labelEl=document.createElement("span"),this.labelEl.className=`${t}__label`,this.valuesEl=document.createElement("div"),this.valuesEl.className=`${t}__values`,this.containerEl=document.createElement("div"),this.containerEl.className=`${t}__container`,this.containerEl.setAttribute("role","slider"),this.containerEl.setAttribute("tabindex","0"),this.trackEl=document.createElement("div"),this.trackEl.className=`${t}__track`,this.fillEl=document.createElement("div"),this.fillEl.className=`${t}__fill`,this.trackEl.appendChild(this.fillEl),this.containerEl.appendChild(this.trackEl)}getValuePosition(){const t=this.getAttribute("value-position");return t||(this.shouldShowLabel()?"top":"right")}shouldShowLabel(){return this.hasAttribute("show-label")&&Boolean(this.getAttribute("label")?.trim())}formatValue(t){const e=this.getAttribute("value-fixed");if(null!==e&&""!==e){const i=Number(e);if(Number.isFinite(i))return t.toFixed(i)}return String(t)}syncDomOrder(){if(!this.headerEl||!this.valuesEl||!this.containerEl)return;const t=this.getValuePosition(),e=this.shouldShowLabel(),i=this.hasAttribute("show-value"),s=this.hasAttribute("range");return this.replaceChildren(),this.labelEl&&(this.labelEl.textContent=this.getAttribute("label")?.trim()||""),s||"top"===t?(this.headerEl.replaceChildren(),e&&this.labelEl&&this.headerEl.appendChild(this.labelEl),i&&this.headerEl.appendChild(this.valuesEl),this.headerEl.childElementCount>0&&this.append(this.headerEl),void this.append(this.containerEl)):"bottom"===t?(e&&this.labelEl&&(this.headerEl.replaceChildren(this.labelEl),this.append(this.headerEl)),this.append(this.containerEl),void(i&&this.append(this.valuesEl))):void(i?this.append(this.valuesEl,this.containerEl):this.append(this.containerEl))}bindEvents(){this.eventsBound||(this.trackEl?.addEventListener("click",this.boundTrackClick),this.containerEl?.addEventListener("keydown",this.boundContainerKeyDown),this.eventsBound=!0)}unbindEvents(){this.eventsBound&&(this.trackEl?.removeEventListener("click",this.boundTrackClick),this.containerEl?.removeEventListener("keydown",this.boundContainerKeyDown),document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.eventsBound=!1)}readAttributeValues(){const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.getNumberAttr("step",1);if(this.hasAttribute("range")){const s=this.parseRangeAttr(this.getAttribute("range"));s?this.currentRange=[this.clamp(s[0],t,e,i),this.clamp(s[1],t,e,i)]:this.currentRange.every(Number.isFinite)||(this.currentRange=[25,75])}else this.currentValue=this.clamp(this.getNumberAttr("value",50),t,e,i)}syncClasses(){const e=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default",s=this.hasAttribute("range"),r=this.getValuePosition(),a=[t,`${t}--${e}`,`${t}--${i}`,`${t}--value-${s?"top":r}`,this.shouldShowLabel()?`${t}--has-label`:"",this.hasAttribute("disabled")?`${t}--disabled`:"",this.hasAttribute("readonly")?`${t}--readonly`:"",this.hasAttribute("full-width")?`${t}--full-width`:"",this.hasAttribute("vertical")?`${t}--vertical`:"",this.hasAttribute("show-thumb-tooltip")?`${t}--show-tooltip`:"",s?`${t}--range`:""].filter(Boolean);if(this.className=a.join(" "),this.trackEl){const e=[`${t}__track`];this.hasAttribute("disabled")&&e.push(`${t}__track--disabled`),this.hasAttribute("readonly")&&e.push(`${t}__track--readonly`),this.trackEl.className=e.join(" ")}}syncStructure(){if(!this.valuesEl||!this.trackEl||!this.fillEl)return;const e=this.hasAttribute("show-value"),i=this.hasAttribute("range"),s=this.hasAttribute("show-marks");if(this.valuesEl.innerHTML="",this.valuesEl.hidden=!e,e)if(i){const e=document.createElement("span");e.className=`${t}__value ${t}__value--min`;const i=document.createElement("span");i.className=`${t}__value-separator`,i.textContent="~",i.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className=`${t}__value ${t}__value--max`,this.valuesEl.append(e,i,s)}else{const e=document.createElement("span");e.className=`${t}__value ${t}__value--single`,this.valuesEl.appendChild(e)}if(this.thumbEls.forEach(t=>t.remove()),this.thumbEls=[],this.trackEl.querySelectorAll(`.${t}__mark`).forEach(t=>t.remove()),s){const e=this.parseMarks();if(e.length>0){const i=this.parseMarkLabels();e.forEach(e=>{const s=document.createElement("div");if(s.className=`${t}__mark`,s.setAttribute("aria-hidden","true"),this.isMarkActive(e)&&s.classList.add(`${t}__mark--active`),this.hasAttribute("vertical")?s.style.bottom=`${this.valueToPercent(e)}%`:s.style.left=`${this.valueToPercent(e)}%`,void 0!==i[e]){const r=document.createElement("span");r.className=`${t}__mark-label`,r.textContent=i[e],s.appendChild(r)}this.trackEl.insertBefore(s,this.fillEl)})}}const r=i?2:1,a=this.hasAttribute("disabled")||this.hasAttribute("readonly");for(let e=0;e<r;e++){const s=document.createElement("div");s.className=`${t}__thumb`,s.setAttribute("role","slider"),s.setAttribute("draggable","false"),s.setAttribute("tabindex",a?"-1":"0");const r=i?0===e?"min":"max":"single";i&&(s.dataset.thumb=r),s.addEventListener("pointerdown",t=>this.handleThumbPointerDown(t,r)),s.addEventListener("keydown",t=>this.handleKeyDown(t,r));const n=document.createElement("span");n.className=`${t}__thumb-tooltip`,n.setAttribute("aria-hidden","true"),n.hidden=!0,s.appendChild(n),this.trackEl.appendChild(s),this.thumbEls.push(s)}}isMarkActive(t){if(this.hasAttribute("range")){const[e,i]=this.currentRange;return t>=e&&t<=i}return t<=this.currentValue}syncVisuals(){if(!this.fillEl)return;const e=this.hasAttribute("range"),i=this.getNumberAttr("min",0),s=this.getNumberAttr("max",100);if(e){const[e,r]=this.currentRange,a=this.valueToPercent(e),n=this.valueToPercent(r);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom=`${a}%`,this.fillEl.style.height=n-a+"%"):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left=`${a}%`,this.fillEl.style.width=n-a+"%"),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],a),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(r)),this.thumbEls[0].setAttribute("aria-valuenow",String(e))),this.thumbEls[1]&&(this.setThumbPosition(this.thumbEls[1],n),this.thumbEls[1].setAttribute("aria-valuemin",String(e)),this.thumbEls[1].setAttribute("aria-valuemax",String(s)),this.thumbEls[1].setAttribute("aria-valuenow",String(r)));const h=this.valuesEl?.querySelector(`.${t}__value--min`),l=this.valuesEl?.querySelector(`.${t}__value--max`);h&&(h.textContent=this.formatValue(e)),l&&(l.textContent=this.formatValue(r))}else{const e=this.valueToPercent(this.currentValue);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom="0",this.fillEl.style.height=`${e}%`):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left="0",this.fillEl.style.width=`${e}%`),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],e),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(s)),this.thumbEls[0].setAttribute("aria-valuenow",String(this.currentValue)));const r=this.valuesEl?.querySelector(`.${t}__value--single`);r&&(r.textContent=this.formatValue(this.currentValue))}this.syncThumbTooltips(),this.trackEl?.querySelectorAll(`.${t}__mark`).forEach(e=>{const i=e instanceof HTMLElement?parseFloat(e.style.left):NaN,s=e instanceof HTMLElement?parseFloat(e.style.bottom):NaN,r=Number.isFinite(i)?i:s;if(!Number.isFinite(r))return;const a=this.percentToValue(r);e.classList.toggle(`${t}__mark--active`,this.isMarkActive(a))})}syncThumbTooltips(){const e=this.hasAttribute("range"),i=this.hasAttribute("show-thumb-tooltip");this.thumbEls.forEach((s,r)=>{const a=s.querySelector(`.${t}__thumb-tooltip`);if(!a)return;if(!i)return void(a.hidden=!0);a.hidden=!1;const n=e?0===r?this.currentRange[0]:this.currentRange[1]:this.currentValue;a.textContent=this.formatValue(n)})}syncA11y(){if(!this.containerEl)return;const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.hasAttribute("range"),s=this.hasAttribute("disabled"),r=this.hasAttribute("readonly");this.containerEl.setAttribute("aria-valuemin",String(t)),this.containerEl.setAttribute("aria-valuemax",String(e)),this.containerEl.setAttribute("aria-valuenow",String(i?this.currentRange[0]:this.currentValue)),this.containerEl.setAttribute("aria-valuetext",i?`${this.currentRange[0]} to ${this.currentRange[1]}`:String(this.currentValue)),this.containerEl.setAttribute("aria-disabled",String(s)),this.containerEl.setAttribute("aria-readonly",String(r)),this.containerEl.setAttribute("tabindex",s||r?"-1":"0")}setThumbPosition(t,e){this.hasAttribute("vertical")?(t.style.left="",t.style.bottom=`${e}%`):(t.style.bottom="",t.style.left=`${e}%`)}valueToPercent(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100);return i===e?0:(t-e)/(i-e)*100}percentToValue(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1),r=e+t/100*(i-e);return this.snapToStep(r,e,i,s)}snapToStep(t,e,i,s){const r=Math.round(t/s)*s;return Math.min(i,Math.max(e,r))}clamp(t,e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1)){return this.snapToStep(Math.min(i,Math.max(e,t)),e,i,s)}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}normalizeRangeInput(t){if("string"==typeof t)return this.parseRangeAttr(t);if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null}parseRangeAttr(t){if(!t)return null;if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e)&&2===e.length){const t=Number(e[0]),i=Number(e[1]);if(Number.isFinite(t)&&Number.isFinite(i))return[t,i]}}catch{return null}return null}const e=t.split(",").map(t=>Number(t.trim()));return 2!==e.length||e.some(t=>!Number.isFinite(t))?null:[e[0],e[1]]}parseMarks(){const t=this.getAttribute("marks");if(!t)return[];if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e))return e.map(t=>Number(t)).filter(t=>Number.isFinite(t))}catch{return[]}return[]}return t.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t))}parseMarkLabels(){const t=this.getAttribute("mark-labels");if(!t)return{};try{const e=JSON.parse(t),i={};return Object.entries(e).forEach(([t,e])=>{i[Number(t)]=e}),i}catch{return{}}}isInteractive(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")}getTrackPercent(t,e){if(!this.trackEl)return 0;const i=this.trackEl.getBoundingClientRect();if(this.hasAttribute("vertical")){const t=Math.max(i.top,Math.min(i.bottom,e));return(i.bottom-t)/i.height*100}return(Math.max(i.left,Math.min(i.right,t))-i.left)/i.width*100}handleThumbPointerDown(t,e){this.isInteractive()&&(t.preventDefault(),this.isDragging=!0,this.activeThumb=e,this.setThumbActive(e,!0),document.addEventListener("pointermove",this.boundPointerMove),document.addEventListener("pointerup",this.boundPointerUp))}handleTrackClick(e){if(!this.isInteractive()||!this.trackEl)return;if(e.target.closest(`.${t}__thumb`))return;const i=this.getTrackPercent(e.clientX,e.clientY),s=this.percentToValue(i);this.commitValueAtPosition(s)}handlePointerMove(t){if(!this.isDragging||!this.isInteractive())return;const e=this.getTrackPercent(t.clientX,t.clientY),i=this.percentToValue(e);this.applyDragValue(i)}handlePointerUp(){this.isDragging&&(this.activeThumb&&this.setThumbActive(this.activeThumb,!1),this.isDragging=!1,this.activeThumb=null,document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.syncThumbTooltips(),this.hasAttribute("range")?this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`):this.setAttribute("value",String(this.currentValue)),this.syncA11y())}setThumbActive(e,i){if(this.hasAttribute("range")){const s=this.thumbEls["min"===e?0:1];return void s?.classList.toggle(`${t}__thumb--active`,i)}this.thumbEls[0]?.classList.toggle(`${t}__thumb--active`,i)}applyDragValue(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange;if("min"===this.activeThumb)this.currentRange=[Math.min(e,i),i];else if("max"===this.activeThumb)this.currentRange=[t,Math.max(e,t)];else{Math.abs(e-t)<=Math.abs(e-i)?(this.currentRange=[Math.min(e,i),i],this.activeThumb="min"):(this.currentRange=[t,Math.max(e,t)],this.activeThumb="max")}this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}commitValueAtPosition(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange,s=Math.abs(e-t),r=Math.abs(e-i);this.currentRange=s<=r?[Math.min(e,i),i]:[t,Math.max(e,t)],this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}handleKeyDown(t,e="single"){if(!this.isInteractive())return;const i=this.getNumberAttr("step",1),s=this.getNumberAttr("min",0),r=this.getNumberAttr("max",100);let a;if(this.hasAttribute("range")&&"single"!==e){const n="min"===e?this.currentRange[0]:this.currentRange[1];switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(n-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(n+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}const h=[...this.currentRange];if("min"===e?h[0]=a:h[1]=a,h[0]>h[1])return;return t.preventDefault(),this.currentRange=h,void this.afterKeyboard()}if(!this.hasAttribute("range")){switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(this.currentValue-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(this.currentValue+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}t.preventDefault(),this.currentValue=a,this.afterKeyboard()}}afterKeyboard(){this.hasAttribute("range")?(this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()):(this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange())}dispatchValueChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.currentValue}}))}dispatchRangeChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{range:[...this.currentRange]}}))}}customElements.get("db-range-slider")||customElements.define("db-range-slider",DbRangeSlider);export{DbRangeSlider};
|
|
1
|
+
const t="designbase-wc-range-slider";class DbRangeSlider extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.headerEl=null,this.labelEl=null,this.valuesEl=null,this.containerEl=null,this.trackEl=null,this.fillEl=null,this.thumbEls=[],this.currentValue=50,this.currentRange=[25,75],this.isDragging=!1,this.activeThumb=null,this.boundTrackClick=t=>this.handleTrackClick(t),this.boundPointerMove=t=>this.handlePointerMove(t),this.boundPointerUp=()=>this.handlePointerUp(),this.boundContainerKeyDown=t=>this.handleKeyDown(t),this.eventsBound=!1}static get observedAttributes(){return["value","range","min","max","step","size","variant","show-value","show-label","label","value-position","value-fixed","show-thumb-tooltip","show-marks","marks","mark-labels","disabled","readonly","full-width","vertical"]}connectedCallback(){this.built||(this.build(),this.built=!0),this.readAttributeValues(),this.syncClasses(),this.syncDomOrder(),this.syncStructure(),this.syncVisuals(),this.syncA11y(),this.bindEvents()}disconnectedCallback(){this.unbindEvents()}attributeChangedCallback(t){this.built&&(this.readAttributeValues(),this.syncClasses(),this.isStructuralAttribute(t)&&(this.syncDomOrder(),this.syncStructure()),this.syncVisuals(),this.syncA11y())}isStructuralAttribute(t){return["range","show-value","show-label","label","value-position","show-marks","marks","mark-labels","vertical"].includes(t)}get value(){return this.currentValue}set value(t){this.currentValue=this.clamp(t),this.setAttribute("value",String(this.currentValue)),this.syncVisuals()}get range(){if(this.hasAttribute("range"))return[...this.currentRange]}set range(t){if(null==t)return this.removeAttribute("range"),void(this.built&&(this.syncStructure(),this.syncVisuals()));const e=this.normalizeRangeInput(t);if(!e)return;const i=[Math.min(e[0],e[1]),Math.max(e[0],e[1])];this.currentRange=[this.clamp(i[0]),this.clamp(i[1])];const s=`${this.currentRange[0]},${this.currentRange[1]}`;this.getAttribute("range")!==s&&this.setAttribute("range",s),this.built&&this.syncVisuals()}build(){this.classList.add(t),this.headerEl=document.createElement("div"),this.headerEl.className=`${t}__header`,this.labelEl=document.createElement("span"),this.labelEl.className=`${t}__label`,this.valuesEl=document.createElement("div"),this.valuesEl.className=`${t}__values`,this.containerEl=document.createElement("div"),this.containerEl.className=`${t}__container`,this.containerEl.setAttribute("role","slider"),this.containerEl.setAttribute("tabindex","0"),this.trackEl=document.createElement("div"),this.trackEl.className=`${t}__track`,this.fillEl=document.createElement("div"),this.fillEl.className=`${t}__fill`,this.trackEl.appendChild(this.fillEl),this.containerEl.appendChild(this.trackEl)}getValuePosition(){const t=this.getAttribute("value-position");return t||(this.shouldShowLabel()?"top":"right")}shouldShowLabel(){return this.hasAttribute("show-label")&&Boolean(this.getAttribute("label")?.trim())}formatValue(t){const e=this.getAttribute("value-fixed");if(null!==e&&""!==e){const i=Number(e);if(Number.isFinite(i))return t.toFixed(i)}return String(t)}syncDomOrder(){if(!this.headerEl||!this.valuesEl||!this.containerEl)return;const t=this.getValuePosition(),e=this.shouldShowLabel(),i=this.hasAttribute("show-value"),s=this.hasAttribute("range");return this.replaceChildren(),this.labelEl&&(this.labelEl.textContent=this.getAttribute("label")?.trim()||""),s||"top"===t?(this.headerEl.replaceChildren(),e&&this.labelEl&&this.headerEl.appendChild(this.labelEl),i&&this.headerEl.appendChild(this.valuesEl),this.headerEl.childElementCount>0&&this.append(this.headerEl),void this.append(this.containerEl)):"bottom"===t?(e&&this.labelEl&&(this.headerEl.replaceChildren(this.labelEl),this.append(this.headerEl)),this.append(this.containerEl),void(i&&this.append(this.valuesEl))):void(i?this.append(this.valuesEl,this.containerEl):this.append(this.containerEl))}bindEvents(){this.eventsBound||(this.trackEl?.addEventListener("click",this.boundTrackClick),this.containerEl?.addEventListener("keydown",this.boundContainerKeyDown),this.eventsBound=!0)}unbindEvents(){this.eventsBound&&(this.trackEl?.removeEventListener("click",this.boundTrackClick),this.containerEl?.removeEventListener("keydown",this.boundContainerKeyDown),document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.eventsBound=!1)}readAttributeValues(){const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.getNumberAttr("step",1);if(this.hasAttribute("range")){const s=this.parseRangeAttr(this.getAttribute("range"));s?this.currentRange=[this.clamp(s[0],t,e,i),this.clamp(s[1],t,e,i)]:this.currentRange.every(Number.isFinite)||(this.currentRange=[25,75])}else this.currentValue=this.clamp(this.getNumberAttr("value",50),t,e,i)}syncClasses(){const e=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default",s=this.hasAttribute("range"),r=this.getValuePosition(),a=s?"top":r,n=this.hasAttribute("show-marks")&&this.parseMarks().length>0&&Object.keys(this.parseMarkLabels()).length>0,h=[t,`${t}--${e}`,`${t}--${i}`,`${t}--value-${a}`,this.shouldShowLabel()?`${t}--has-label`:"",this.hasAttribute("disabled")?`${t}--disabled`:"",this.hasAttribute("readonly")?`${t}--readonly`:"",this.hasAttribute("full-width")?`${t}--full-width`:"",this.hasAttribute("vertical")?`${t}--vertical`:"",this.hasAttribute("show-thumb-tooltip")?`${t}--show-tooltip`:"",s?`${t}--range`:"",n?`${t}--has-mark-labels`:""].filter(Boolean);if(this.className=h.join(" "),this.trackEl){const e=[`${t}__track`];this.hasAttribute("disabled")&&e.push(`${t}__track--disabled`),this.hasAttribute("readonly")&&e.push(`${t}__track--readonly`),this.trackEl.className=e.join(" ")}}syncStructure(){if(!this.valuesEl||!this.trackEl||!this.fillEl)return;const e=this.hasAttribute("show-value"),i=this.hasAttribute("range"),s=this.hasAttribute("show-marks");if(this.valuesEl.innerHTML="",this.valuesEl.hidden=!e,e)if(i){const e=document.createElement("span");e.className=`${t}__value ${t}__value--min`;const i=document.createElement("span");i.className=`${t}__value-separator`,i.textContent="~",i.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className=`${t}__value ${t}__value--max`,this.valuesEl.append(e,i,s)}else{const e=document.createElement("span");e.className=`${t}__value ${t}__value--single`,this.valuesEl.appendChild(e)}if(this.thumbEls.forEach(t=>t.remove()),this.thumbEls=[],this.trackEl.querySelectorAll(`.${t}__mark`).forEach(t=>t.remove()),s){const e=this.parseMarks();if(e.length>0){const i=this.parseMarkLabels();e.forEach(e=>{const s=document.createElement("div");if(s.className=`${t}__mark`,s.setAttribute("aria-hidden","true"),this.isMarkActive(e)&&s.classList.add(`${t}__mark--active`),this.hasAttribute("vertical")?s.style.bottom=`${this.valueToPercent(e)}%`:s.style.left=`${this.valueToPercent(e)}%`,void 0!==i[e]){const r=document.createElement("span");r.className=`${t}__mark-label`,r.textContent=i[e],s.appendChild(r)}this.trackEl.insertBefore(s,this.fillEl)})}}const r=i?2:1,a=this.hasAttribute("disabled")||this.hasAttribute("readonly");for(let e=0;e<r;e++){const s=document.createElement("div");s.className=`${t}__thumb`,s.setAttribute("role","slider"),s.setAttribute("draggable","false"),s.setAttribute("tabindex",a?"-1":"0");const r=i?0===e?"min":"max":"single";i&&(s.dataset.thumb=r),s.addEventListener("pointerdown",t=>this.handleThumbPointerDown(t,r)),s.addEventListener("keydown",t=>this.handleKeyDown(t,r));const n=document.createElement("span");n.className=`${t}__thumb-tooltip`,n.setAttribute("aria-hidden","true"),n.hidden=!0,s.appendChild(n),this.trackEl.appendChild(s),this.thumbEls.push(s)}}isMarkActive(t){if(this.hasAttribute("range")){const[e,i]=this.currentRange;return t>=e&&t<=i}return t<=this.currentValue}syncVisuals(){if(!this.fillEl)return;const e=this.hasAttribute("range"),i=this.getNumberAttr("min",0),s=this.getNumberAttr("max",100);if(e){const[e,r]=this.currentRange,a=this.valueToPercent(e),n=this.valueToPercent(r);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom=`${a}%`,this.fillEl.style.height=n-a+"%"):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left=`${a}%`,this.fillEl.style.width=n-a+"%"),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],a),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(r)),this.thumbEls[0].setAttribute("aria-valuenow",String(e))),this.thumbEls[1]&&(this.setThumbPosition(this.thumbEls[1],n),this.thumbEls[1].setAttribute("aria-valuemin",String(e)),this.thumbEls[1].setAttribute("aria-valuemax",String(s)),this.thumbEls[1].setAttribute("aria-valuenow",String(r)));const h=this.valuesEl?.querySelector(`.${t}__value--min`),l=this.valuesEl?.querySelector(`.${t}__value--max`);h&&(h.textContent=this.formatValue(e)),l&&(l.textContent=this.formatValue(r))}else{const e=this.valueToPercent(this.currentValue);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom="0",this.fillEl.style.height=`${e}%`):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left="0",this.fillEl.style.width=`${e}%`),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],e),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(s)),this.thumbEls[0].setAttribute("aria-valuenow",String(this.currentValue)));const r=this.valuesEl?.querySelector(`.${t}__value--single`);r&&(r.textContent=this.formatValue(this.currentValue))}this.syncThumbTooltips(),this.trackEl?.querySelectorAll(`.${t}__mark`).forEach(e=>{const i=e instanceof HTMLElement?parseFloat(e.style.left):NaN,s=e instanceof HTMLElement?parseFloat(e.style.bottom):NaN,r=Number.isFinite(i)?i:s;if(!Number.isFinite(r))return;const a=this.percentToValue(r);e.classList.toggle(`${t}__mark--active`,this.isMarkActive(a))})}syncThumbTooltips(){const e=this.hasAttribute("range"),i=this.hasAttribute("show-thumb-tooltip");this.thumbEls.forEach((s,r)=>{const a=s.querySelector(`.${t}__thumb-tooltip`);if(!a)return;if(!i)return void(a.hidden=!0);a.hidden=!1;const n=e?0===r?this.currentRange[0]:this.currentRange[1]:this.currentValue;a.textContent=this.formatValue(n)})}syncA11y(){if(!this.containerEl)return;const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.hasAttribute("range"),s=this.hasAttribute("disabled"),r=this.hasAttribute("readonly");this.containerEl.setAttribute("aria-valuemin",String(t)),this.containerEl.setAttribute("aria-valuemax",String(e)),this.containerEl.setAttribute("aria-valuenow",String(i?this.currentRange[0]:this.currentValue)),this.containerEl.setAttribute("aria-valuetext",i?`${this.currentRange[0]} to ${this.currentRange[1]}`:String(this.currentValue)),this.containerEl.setAttribute("aria-disabled",String(s)),this.containerEl.setAttribute("aria-readonly",String(r)),this.containerEl.setAttribute("tabindex",s||r?"-1":"0")}setThumbPosition(t,e){this.hasAttribute("vertical")?(t.style.left="",t.style.bottom=`${e}%`):(t.style.bottom="",t.style.left=`${e}%`)}valueToPercent(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100);return i===e?0:(t-e)/(i-e)*100}percentToValue(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1),r=e+t/100*(i-e);return this.snapToStep(r,e,i,s)}snapToStep(t,e,i,s){const r=Math.round(t/s)*s;return Math.min(i,Math.max(e,r))}clamp(t,e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1)){return this.snapToStep(Math.min(i,Math.max(e,t)),e,i,s)}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}normalizeRangeInput(t){if("string"==typeof t)return this.parseRangeAttr(t);if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null}parseRangeAttr(t){if(!t)return null;if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e)&&2===e.length){const t=Number(e[0]),i=Number(e[1]);if(Number.isFinite(t)&&Number.isFinite(i))return[t,i]}}catch{return null}return null}const e=t.split(",").map(t=>Number(t.trim()));return 2!==e.length||e.some(t=>!Number.isFinite(t))?null:[e[0],e[1]]}parseMarks(){const t=this.getAttribute("marks");if(!t)return[];if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e))return e.map(t=>Number(t)).filter(t=>Number.isFinite(t))}catch{return[]}return[]}return t.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t))}parseMarkLabels(){const t=this.getAttribute("mark-labels");if(!t)return{};try{const e=JSON.parse(t),i={};return Object.entries(e).forEach(([t,e])=>{i[Number(t)]=e}),i}catch{return{}}}isInteractive(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")}getTrackPercent(t,e){if(!this.trackEl)return 0;const i=this.trackEl.getBoundingClientRect();if(this.hasAttribute("vertical")){const t=Math.max(i.top,Math.min(i.bottom,e));return(i.bottom-t)/i.height*100}return(Math.max(i.left,Math.min(i.right,t))-i.left)/i.width*100}handleThumbPointerDown(t,e){this.isInteractive()&&(t.preventDefault(),this.isDragging=!0,this.activeThumb=e,this.setThumbActive(e,!0),document.addEventListener("pointermove",this.boundPointerMove),document.addEventListener("pointerup",this.boundPointerUp))}handleTrackClick(e){if(!this.isInteractive()||!this.trackEl)return;if(e.target.closest(`.${t}__thumb`))return;const i=this.getTrackPercent(e.clientX,e.clientY),s=this.percentToValue(i);this.commitValueAtPosition(s)}handlePointerMove(t){if(!this.isDragging||!this.isInteractive())return;const e=this.getTrackPercent(t.clientX,t.clientY),i=this.percentToValue(e);this.applyDragValue(i)}handlePointerUp(){this.isDragging&&(this.activeThumb&&this.setThumbActive(this.activeThumb,!1),this.isDragging=!1,this.activeThumb=null,document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.syncThumbTooltips(),this.hasAttribute("range")?this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`):this.setAttribute("value",String(this.currentValue)),this.syncA11y())}setThumbActive(e,i){if(this.hasAttribute("range")){const s=this.thumbEls["min"===e?0:1];return void s?.classList.toggle(`${t}__thumb--active`,i)}this.thumbEls[0]?.classList.toggle(`${t}__thumb--active`,i)}applyDragValue(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange;if("min"===this.activeThumb)this.currentRange=[Math.min(e,i),i];else if("max"===this.activeThumb)this.currentRange=[t,Math.max(e,t)];else{Math.abs(e-t)<=Math.abs(e-i)?(this.currentRange=[Math.min(e,i),i],this.activeThumb="min"):(this.currentRange=[t,Math.max(e,t)],this.activeThumb="max")}this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}commitValueAtPosition(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange,s=Math.abs(e-t),r=Math.abs(e-i);this.currentRange=s<=r?[Math.min(e,i),i]:[t,Math.max(e,t)],this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}handleKeyDown(t,e="single"){if(!this.isInteractive())return;const i=this.getNumberAttr("step",1),s=this.getNumberAttr("min",0),r=this.getNumberAttr("max",100);let a;if(this.hasAttribute("range")&&"single"!==e){const n="min"===e?this.currentRange[0]:this.currentRange[1];switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(n-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(n+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}const h=[...this.currentRange];if("min"===e?h[0]=a:h[1]=a,h[0]>h[1])return;return t.preventDefault(),this.currentRange=h,void this.afterKeyboard()}if(!this.hasAttribute("range")){switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(this.currentValue-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(this.currentValue+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}t.preventDefault(),this.currentValue=a,this.afterKeyboard()}}afterKeyboard(){this.hasAttribute("range")?(this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()):(this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange())}dispatchValueChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.currentValue}}))}dispatchRangeChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{range:[...this.currentRange]}}))}}customElements.get("db-range-slider")||customElements.define("db-range-slider",DbRangeSlider);export{DbRangeSlider};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getDbComponentIconSize as e,createDbIcon as t}from"./db-icons.js";const s=["s","m","l"],a=["vertical","horizontal"];class DbSearchBar extends HTMLElement{constructor(){super(...arguments),this.recentSearches=[],this.isFocused=!1,this.currentSuggestion=0,this.scrollParents=[]}static get observedAttributes(){return["value","default-value","placeholder","size","disabled","readonly","full-width","show-shortcut","shortcut-label","enable-recent-searches","recent-searches-key","recent-searches-layout","suggested-searches","suggestion-rolling-interval","categories","selected-category","search-results","empty-state-message"]}getResolvedSize(){const e=this.getAttribute("size")||"m";return s.includes(e)?e:"m"}getIconPx(){return e(this.getResolvedSize())}syncIcons(){const e=this.getIconPx();this.querySelector(".designbase-wc-search-bar__search-icon")?.replaceChildren(t("search",e)),this.clearButton?.replaceChildren(t("close",e))}hasInputValue(){return Boolean((this.input?.value??this.getAttribute("value")??"").trim())}get value(){return this.input?.value??this.getAttribute("value")??""}set value(e){this.setAttribute("value",e),this.input&&(this.input.value=e)}connectedCallback(){this.loadRecentSearches(),this.render(),this.bindGlobalShortcut()}disconnectedCallback(){this.clearSuggestionInterval(),this.unbindGlobalShortcut(),this.detachDropdownPortal(),this.blurTimer&&clearTimeout(this.blurTimer)}attributeChangedCallback(e){if(this.isConnected)return"value"===e&&this.input?(this.input.value=this.getAttribute("value")||"",this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),void this.syncSuggestionRolling()):"disabled"===e||"readonly"===e||"placeholder"===e||"show-shortcut"===e||"shortcut-label"===e||"selected-category"===e||"search-results"===e||"empty-state-message"===e||"suggested-searches"===e?(this.syncAttributes(),this.syncPlaceholder(),this.updateDropdown(),void this.syncSuggestionRolling()):"enable-recent-searches"===e||"recent-searches-key"===e?(this.loadRecentSearches(),void this.updateDropdown()):void("categories"!==e&&"recent-searches-layout"!==e?this.render():this.updateDropdown())}focus(){this.input?.focus()}parseJsonArray(e){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}getRecentSearchesKey(){return this.getAttribute("recent-searches-key")||"searchbar-recent-searches"}loadRecentSearches(){if(this.hasAttribute("enable-recent-searches"))try{const e=localStorage.getItem(this.getRecentSearchesKey());this.recentSearches=e?JSON.parse(e):[],Array.isArray(this.recentSearches)||(this.recentSearches=[])}catch{this.recentSearches=[]}else this.recentSearches=[]}saveRecentSearches(){try{localStorage.setItem(this.getRecentSearchesKey(),JSON.stringify(this.recentSearches))}catch{}}clearSuggestionInterval(){this.suggestionInterval&&(clearInterval(this.suggestionInterval),this.suggestionInterval=void 0)}syncSuggestionRolling(){this.clearSuggestionInterval();const e=this.parseJsonArray("suggested-searches"),t=this.hasInputValue(),s=Number(this.getAttribute("suggestion-rolling-interval")||5e3);e.length>0&&!t&&(this.suggestionInterval=setInterval(()=>{this.currentSuggestion=(this.currentSuggestion+1)%e.length,this.syncPlaceholder(),this.updateDropdown()},s))}syncPlaceholder(){if(!this.input)return;const e=this.parseJsonArray("suggested-searches"),t=this.hasInputValue(),s=this.getAttribute("placeholder")||"검색...";e.length>0&&!t?this.input.placeholder=e[this.currentSuggestion]||s:this.input.placeholder=s}syncValueState(){const e=this.hasInputValue();this.classList.toggle("designbase-wc-search-bar--has-value",e),this.clearButton&&(this.clearButton.hidden=!e||this.hasAttribute("disabled")||this.hasAttribute("readonly")),this.shortcutBadge&&(this.shortcutBadge.hidden=!this.hasAttribute("show-shortcut")||e||this.hasAttribute("disabled")||this.hasAttribute("readonly")),this.syncIcons()}syncAttributes(){const e=this.getAttribute("size")||"m",t=this.hasAttribute("disabled"),a=this.hasAttribute("readonly"),n=this.hasAttribute("show-shortcut");this.className=["designbase-wc-search-bar",`designbase-wc-search-bar--${s.includes(e)?e:"m"}`,t&&"designbase-wc-search-bar--disabled",a&&"designbase-wc-search-bar--readonly",this.hasAttribute("full-width")&&"designbase-wc-search-bar--full-width",Boolean(this.hasInputValue())&&"designbase-wc-search-bar--has-value"].filter(Boolean).join(" "),this.input&&(this.input.disabled=t,this.input.readOnly=a),this.shortcutBadge&&(this.shortcutBadge.hidden=!n||this.hasInputValue()||t||a,this.shortcutBadge.textContent=this.getAttribute("shortcut-label")||"⌘K"),this.syncValueState()}bindGlobalShortcut(){this.unbindGlobalShortcut(),!this.hasAttribute("show-shortcut")||this.hasAttribute("disabled")||this.hasAttribute("readonly")||(this.globalKeyHandler=e=>{const t=e.metaKey||e.ctrlKey;let s="k";const a=(this.getAttribute("shortcut-label")||"⌘K").slice(-1).toLowerCase();a&&(s=a),t&&e.key.toLowerCase()===s&&(e.preventDefault(),this.focus())},window.addEventListener("keydown",this.globalKeyHandler))}unbindGlobalShortcut(){this.globalKeyHandler&&(window.removeEventListener("keydown",this.globalKeyHandler),this.globalKeyHandler=void 0)}positionDropdown(){if(!this.dropdown||this.dropdown.hidden)return;const e=this.getBoundingClientRect(),t=this.input?.getBoundingClientRect(),s=t??e;this.dropdown.style.top=`${s.bottom+4}px`,this.dropdown.style.left=`${e.left}px`,this.dropdown.style.width=`${e.width}px`,this.dropdown.style.right="auto"}bindRepositionListeners(){if(this.repositionHandler)return;this.repositionHandler=()=>{requestAnimationFrame(()=>this.positionDropdown())},window.addEventListener("scroll",this.repositionHandler,!0),window.addEventListener("resize",this.repositionHandler),this.scrollParents=[];let e=this.parentElement;for(;e&&e!==document.body;){const t=getComputedStyle(e),s=/(auto|scroll|overlay)/.test(t.overflowY),a=/(auto|scroll|overlay)/.test(t.overflow);(s||a)&&e.scrollHeight>e.clientHeight&&(e.addEventListener("scroll",this.repositionHandler,{passive:!0}),this.scrollParents.push(e)),e=e.parentElement}}unbindRepositionListeners(){this.repositionHandler&&(window.removeEventListener("scroll",this.repositionHandler,!0),window.removeEventListener("resize",this.repositionHandler),this.scrollParents.forEach(e=>e.removeEventListener("scroll",this.repositionHandler)),this.scrollParents=[],this.repositionHandler=void 0)}attachDropdownPortal(){this.dropdown&&!this.dropdown.hidden&&(this.dropdown.classList.add("designbase-wc-search-bar__dropdown--portal"),this.dropdown.parentElement!==document.body&&document.body.append(this.dropdown),requestAnimationFrame(()=>this.positionDropdown()),this.repositionHandler||this.bindRepositionListeners())}detachDropdownPortal(){this.unbindRepositionListeners(),this.dropdown&&(this.dropdown.classList.remove("designbase-wc-search-bar__dropdown--portal"),this.dropdown.style.top="",this.dropdown.style.left="",this.dropdown.style.width="",this.dropdown.style.right="",this.dropdown.parentElement===document.body&&this.isConnected&&this.append(this.dropdown))}shouldShowDropdown(){const e=this.hasInputValue(),t=this.parseJsonArray("categories"),s=this.parseJsonArray("suggested-searches"),a=this.getAttribute("search-results"),n=this.getAttribute("empty-state-message");return this.isFocused&&(t.length>0||this.hasAttribute("enable-recent-searches")&&this.recentSearches.length>0&&!e||s.length>0&&!e||null!==a&&e||Boolean(n)&&!e&&(!this.hasAttribute("enable-recent-searches")||0===this.recentSearches.length)&&0===s.length)}formatSearchResult(e){if("string"==typeof e||"number"==typeof e)return String(e);if(e&&"object"==typeof e){const t=e;if("string"==typeof t.title)return t.title;if("string"==typeof t.label)return t.label}return String(e)}handleSearch(e){const t=(e??this.value).trim();t&&(this.dispatchEvent(new CustomEvent("db-search",{detail:{value:t},bubbles:!0,composed:!0})),this.hasAttribute("enable-recent-searches")&&(this.recentSearches=[t,...this.recentSearches.filter(e=>e!==t)].slice(0,10),this.saveRecentSearches(),this.updateDropdown()))}updateDropdown(){if(!this.dropdown)return;const s=this.shouldShowDropdown();if(this.dropdown.hidden=!s,this.classList.toggle("designbase-wc-search-bar--dropdown-open",s),!s)return this.dropdown.replaceChildren(),void this.detachDropdownPortal();this.dropdown.replaceChildren();const n=this.hasInputValue(),r=this.parseJsonArray("categories"),i=this.parseJsonArray("suggested-searches"),o=this.getAttribute("selected-category")||"",c=this.parseJsonArray("search-results"),h=this.getAttribute("empty-state-message"),d=a.includes(this.getAttribute("recent-searches-layout")||"vertical")&&this.getAttribute("recent-searches-layout")||"vertical";if(r.length>0){const e=document.createElement("div");e.className="designbase-wc-search-bar__categories",r.forEach(t=>{const s=document.createElement("db-chip");s.setAttribute("label",t),s.setAttribute("size","s"),s.setAttribute("variant",t===o?"primary":"default"),s.setAttribute("clickable",""),s.addEventListener("mousedown",e=>{e.preventDefault(),this.setAttribute("selected-category",t),this.dispatchEvent(new CustomEvent("db-category-change",{detail:{category:t},bubbles:!0,composed:!0})),this.updateDropdown()}),e.append(s)}),this.dropdown.append(e)}if(n&&this.hasAttribute("search-results")){const e=document.createElement("div");if(e.className="designbase-wc-search-bar__results",c.length>0){const t=document.createElement("ul");t.className="designbase-wc-search-bar__results-list",c.forEach((e,s)=>{const a=document.createElement("li");a.className="designbase-wc-search-bar__result-item",a.textContent=this.formatSearchResult(e),a.addEventListener("mousedown",t=>{t.preventDefault(),this.isFocused=!1,this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-search-result-click",{detail:{result:e,index:s},bubbles:!0,composed:!0}))}),t.append(a)}),e.append(t)}else{const t=document.createElement("div");t.className="designbase-wc-search-bar__results-empty",t.textContent="검색 결과가 없습니다.",e.append(t)}return this.dropdown.append(e),void this.attachDropdownPortal()}if(this.hasAttribute("enable-recent-searches")&&!n&&this.recentSearches.length>0){const s=document.createElement("div");s.className=`designbase-wc-search-bar__recent-searches designbase-wc-search-bar__recent-searches--${d}`;const a=document.createElement("div");a.className="designbase-wc-search-bar__recent-header";const n=document.createElement("span");n.className="designbase-wc-search-bar__recent-title",n.textContent="최근 검색어";const r=document.createElement("button");r.type="button",r.className="designbase-wc-search-bar__clear-all-button",r.setAttribute("aria-label","모든 최근 검색어 삭제"),r.textContent="전체 삭제",r.addEventListener("mousedown",e=>{e.preventDefault(),this.recentSearches=[];try{localStorage.removeItem(this.getRecentSearchesKey())}catch{}this.updateDropdown()}),a.append(n,r);const i=document.createElement("div");i.className="designbase-wc-search-bar__recent-list",this.recentSearches.forEach(s=>{const a=document.createElement("div");a.className="designbase-wc-search-bar__recent-item";const n=document.createElement("button");n.type="button",n.className="designbase-wc-search-bar__recent-search-button",n.textContent=s,n.addEventListener("mousedown",e=>{if(e.preventDefault(),!this.input)return;this.input.value=s,this.setAttribute("value",s),this.syncValueState(),this.syncPlaceholder(),this.handleSearch(s);const t={value:s};this.dispatchEvent(new CustomEvent("db-input",{detail:t,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:t,bubbles:!0,composed:!0})),this.isFocused=!1,this.updateDropdown()});const r=document.createElement("button");r.type="button",r.className="designbase-wc-search-bar__recent-remove-button",r.setAttribute("aria-label",`${s} 삭제`),r.append(t("close",e("s"))),r.addEventListener("mousedown",e=>{e.preventDefault(),this.recentSearches=this.recentSearches.filter(e=>e!==s),this.saveRecentSearches(),this.updateDropdown()}),a.append(n,r),i.append(a)}),s.append(a,i),this.dropdown.append(s)}if(i.length>0&&!n){const e=document.createElement("div");e.className="designbase-wc-search-bar__suggestions";const t=document.createElement("div");t.className="designbase-wc-search-bar__suggestions-header";const s=document.createElement("span");s.className="designbase-wc-search-bar__suggestions-title",s.textContent="추천 검색어",t.append(s);const a=document.createElement("div");a.className="designbase-wc-search-bar__suggestions-list",i.forEach((e,t)=>{const s=document.createElement("button");s.type="button",s.className=["designbase-wc-search-bar__suggestion-item",t===this.currentSuggestion&&"designbase-wc-search-bar__suggestion-item--active"].filter(Boolean).join(" "),s.textContent=e,s.addEventListener("mousedown",t=>{if(t.preventDefault(),!this.input)return;this.clearSuggestionInterval(),this.input.value=e,this.setAttribute("value",e),this.syncValueState(),this.syncPlaceholder(),this.handleSearch(e);const s={value:e};this.dispatchEvent(new CustomEvent("db-input",{detail:s,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:s,bubbles:!0,composed:!0})),this.isFocused=!1,this.updateDropdown()}),a.append(s)}),e.append(t,a),this.dropdown.append(e)}if(h&&!n&&(!this.hasAttribute("enable-recent-searches")||0===this.recentSearches.length)&&0===i.length){const e=document.createElement("div");e.className="designbase-wc-search-bar__empty-state",e.textContent=h,this.dropdown.append(e)}this.attachDropdownPortal()}render(){const e=this.getAttribute("size")||"m",a=this.hasAttribute("disabled"),n=this.hasAttribute("readonly"),r=this.hasAttribute("full-width"),i=this.hasAttribute("show-shortcut"),o=this.getAttribute("value")??this.getAttribute("default-value")??"",c=Boolean(o.trim()),h=this.getIconPx();this.className=["designbase-wc-search-bar",`designbase-wc-search-bar--${s.includes(e)?e:"m"}`,a&&"designbase-wc-search-bar--disabled",n&&"designbase-wc-search-bar--readonly",r&&"designbase-wc-search-bar--full-width",c&&"designbase-wc-search-bar--has-value",this.shouldShowDropdown()&&"designbase-wc-search-bar--dropdown-open"].filter(Boolean).join(" "),this.setAttribute("role","search"),this.clearSuggestionInterval(),this.detachDropdownPortal(),this.replaceChildren();const d=document.createElement("div");d.className="designbase-wc-search-bar__container";const l=document.createElement("div");l.className="designbase-wc-search-bar__search-icon",l.setAttribute("aria-hidden","true"),l.append(t("search",h));const u=document.createElement("input");if(u.type="text",u.className="designbase-wc-search-bar__input",u.value=o,u.disabled=a,u.readOnly=n,u.setAttribute("aria-label","검색어 입력"),this.input=u,i){const t=document.createElement("db-badge");t.className="designbase-wc-search-bar__shortcut-badge",t.setAttribute("size","l"===e?"m":"s"),t.setAttribute("variant","secondary"),t.setAttribute("badge-style","text"),t.setAttribute("aria-hidden","true"),t.textContent=this.getAttribute("shortcut-label")||"⌘K",t.hidden=c||a||n,this.shortcutBadge=t,d.append(l,u,t)}else d.append(l,u);const b=document.createElement("button");b.type="button",b.className="designbase-wc-search-bar__clear-button",b.setAttribute("aria-label","검색어 지우기"),b.hidden=!c||a||n,b.append(t("close",h)),this.clearButton=b,d.append(b);const p=document.createElement("div");p.className="designbase-wc-search-bar__dropdown",p.hidden=!0,p.addEventListener("mousedown",e=>{e.preventDefault()}),this.dropdown=p,u.addEventListener("input",()=>{this.setAttribute("value",u.value),this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),this.syncSuggestionRolling();const e={value:u.value};this.dispatchEvent(new CustomEvent("db-input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:e,bubbles:!0,composed:!0}))}),u.addEventListener("keydown",e=>{"Enter"===e.key&&this.handleSearch()}),u.addEventListener("focus",()=>{this.isFocused=!0,this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),u.addEventListener("blur",()=>{this.isFocused=!1,this.blurTimer&&clearTimeout(this.blurTimer),this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),b.addEventListener("click",()=>{u.value="",this.setAttribute("value",""),this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),this.syncSuggestionRolling(),u.focus(),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0}));const e={value:""};this.dispatchEvent(new CustomEvent("db-input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:e,bubbles:!0,composed:!0}))}),this.append(d,p),this.syncIcons(),this.syncPlaceholder(),this.syncSuggestionRolling(),this.bindGlobalShortcut(),this.updateDropdown()}}customElements.get("db-search-bar")||customElements.define("db-search-bar",DbSearchBar);export{DbSearchBar};
|
|
1
|
+
import{getDbComponentIconSize as e,createDbIcon as t}from"./db-icons.js";const s=["s","m","l"],a=["vertical","horizontal"];class DbSearchBar extends HTMLElement{constructor(){super(...arguments),this.recentSearches=[],this.isFocused=!1,this.currentSuggestion=0,this.scrollParents=[]}static get observedAttributes(){return["value","default-value","placeholder","size","appearance","disabled","readonly","full-width","show-shortcut","shortcut-label","enable-recent-searches","recent-searches-key","recent-searches-layout","suggested-searches","suggestion-rolling-interval","categories","selected-category","search-results","empty-state-message"]}getResolvedSize(){const e=this.getAttribute("size")||"m";return s.includes(e)?e:"m"}getIconPx(){return e(this.getResolvedSize())}syncIcons(){const e=this.getIconPx();this.querySelector(".designbase-wc-search-bar__search-icon")?.replaceChildren(t("search",e)),this.clearButton?.replaceChildren(t("close",e))}hasInputValue(){return Boolean((this.input?.value??this.getAttribute("value")??"").trim())}get value(){return this.input?.value??this.getAttribute("value")??""}set value(e){this.setAttribute("value",e),this.input&&(this.input.value=e)}connectedCallback(){this.loadRecentSearches(),this.render(),this.bindGlobalShortcut()}disconnectedCallback(){this.clearSuggestionInterval(),this.unbindGlobalShortcut(),this.detachDropdownPortal(),this.blurTimer&&clearTimeout(this.blurTimer)}attributeChangedCallback(e){if(this.isConnected)return"value"===e&&this.input?(this.input.value=this.getAttribute("value")||"",this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),void this.syncSuggestionRolling()):"disabled"===e||"readonly"===e||"placeholder"===e||"show-shortcut"===e||"shortcut-label"===e||"selected-category"===e||"search-results"===e||"empty-state-message"===e||"suggested-searches"===e?(this.syncAttributes(),this.syncPlaceholder(),this.updateDropdown(),void this.syncSuggestionRolling()):"enable-recent-searches"===e||"recent-searches-key"===e?(this.loadRecentSearches(),void this.updateDropdown()):void("categories"!==e&&"recent-searches-layout"!==e?this.render():this.updateDropdown())}focus(){this.input?.focus()}parseJsonArray(e){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}getRecentSearchesKey(){return this.getAttribute("recent-searches-key")||"searchbar-recent-searches"}loadRecentSearches(){if(this.hasAttribute("enable-recent-searches"))try{const e=localStorage.getItem(this.getRecentSearchesKey());this.recentSearches=e?JSON.parse(e):[],Array.isArray(this.recentSearches)||(this.recentSearches=[])}catch{this.recentSearches=[]}else this.recentSearches=[]}saveRecentSearches(){try{localStorage.setItem(this.getRecentSearchesKey(),JSON.stringify(this.recentSearches))}catch{}}clearSuggestionInterval(){this.suggestionInterval&&(clearInterval(this.suggestionInterval),this.suggestionInterval=void 0)}syncSuggestionRolling(){this.clearSuggestionInterval();const e=this.parseJsonArray("suggested-searches"),t=this.hasInputValue(),s=Number(this.getAttribute("suggestion-rolling-interval")||5e3);e.length>0&&!t&&(this.suggestionInterval=setInterval(()=>{this.currentSuggestion=(this.currentSuggestion+1)%e.length,this.syncPlaceholder(),this.updateDropdown()},s))}syncPlaceholder(){if(!this.input)return;const e=this.parseJsonArray("suggested-searches"),t=this.hasInputValue(),s=this.getAttribute("placeholder")||"검색...";e.length>0&&!t?this.input.placeholder=e[this.currentSuggestion]||s:this.input.placeholder=s}syncValueState(){const e=this.hasInputValue();this.classList.toggle("designbase-wc-search-bar--has-value",e),this.clearButton&&(this.clearButton.hidden=!e||this.hasAttribute("disabled")||this.hasAttribute("readonly")),this.shortcutBadge&&(this.shortcutBadge.hidden=!this.hasAttribute("show-shortcut")||e||this.hasAttribute("disabled")||this.hasAttribute("readonly")),this.syncIcons()}syncAttributes(){const e=this.getAttribute("size")||"m",t=this.hasAttribute("disabled"),a=this.hasAttribute("readonly"),n=this.hasAttribute("show-shortcut");this.className=["designbase-wc-search-bar",`designbase-wc-search-bar--${s.includes(e)?e:"m"}`,"pill"===this.getAttribute("appearance")&&"designbase-wc-search-bar--appearance-pill",t&&"designbase-wc-search-bar--disabled",a&&"designbase-wc-search-bar--readonly",this.hasAttribute("full-width")&&"designbase-wc-search-bar--full-width",Boolean(this.hasInputValue())&&"designbase-wc-search-bar--has-value"].filter(Boolean).join(" "),this.input&&(this.input.disabled=t,this.input.readOnly=a),this.shortcutBadge&&(this.shortcutBadge.hidden=!n||this.hasInputValue()||t||a,this.shortcutBadge.textContent=this.getAttribute("shortcut-label")||"⌘K"),this.syncValueState()}bindGlobalShortcut(){this.unbindGlobalShortcut(),!this.hasAttribute("show-shortcut")||this.hasAttribute("disabled")||this.hasAttribute("readonly")||(this.globalKeyHandler=e=>{const t=e.metaKey||e.ctrlKey;let s="k";const a=(this.getAttribute("shortcut-label")||"⌘K").slice(-1).toLowerCase();a&&(s=a),t&&e.key.toLowerCase()===s&&(e.preventDefault(),this.focus())},window.addEventListener("keydown",this.globalKeyHandler))}unbindGlobalShortcut(){this.globalKeyHandler&&(window.removeEventListener("keydown",this.globalKeyHandler),this.globalKeyHandler=void 0)}positionDropdown(){if(!this.dropdown||this.dropdown.hidden)return;const e=this.getBoundingClientRect(),t=this.input?.getBoundingClientRect(),s=t??e;this.dropdown.style.top=`${s.bottom+4}px`,this.dropdown.style.left=`${e.left}px`,this.dropdown.style.width=`${e.width}px`,this.dropdown.style.right="auto"}bindRepositionListeners(){if(this.repositionHandler)return;this.repositionHandler=()=>{requestAnimationFrame(()=>this.positionDropdown())},window.addEventListener("scroll",this.repositionHandler,!0),window.addEventListener("resize",this.repositionHandler),this.scrollParents=[];let e=this.parentElement;for(;e&&e!==document.body;){const t=getComputedStyle(e),s=/(auto|scroll|overlay)/.test(t.overflowY),a=/(auto|scroll|overlay)/.test(t.overflow);(s||a)&&e.scrollHeight>e.clientHeight&&(e.addEventListener("scroll",this.repositionHandler,{passive:!0}),this.scrollParents.push(e)),e=e.parentElement}}unbindRepositionListeners(){this.repositionHandler&&(window.removeEventListener("scroll",this.repositionHandler,!0),window.removeEventListener("resize",this.repositionHandler),this.scrollParents.forEach(e=>e.removeEventListener("scroll",this.repositionHandler)),this.scrollParents=[],this.repositionHandler=void 0)}attachDropdownPortal(){this.dropdown&&!this.dropdown.hidden&&(this.dropdown.classList.add("designbase-wc-search-bar__dropdown--portal"),this.dropdown.parentElement!==document.body&&document.body.append(this.dropdown),requestAnimationFrame(()=>this.positionDropdown()),this.repositionHandler||this.bindRepositionListeners())}detachDropdownPortal(){this.unbindRepositionListeners(),this.dropdown&&(this.dropdown.classList.remove("designbase-wc-search-bar__dropdown--portal"),this.dropdown.style.top="",this.dropdown.style.left="",this.dropdown.style.width="",this.dropdown.style.right="",this.dropdown.parentElement===document.body&&this.isConnected&&this.append(this.dropdown))}shouldShowDropdown(){const e=this.hasInputValue(),t=this.parseJsonArray("categories"),s=this.parseJsonArray("suggested-searches"),a=this.getAttribute("search-results"),n=this.getAttribute("empty-state-message");return this.isFocused&&(t.length>0||this.hasAttribute("enable-recent-searches")&&this.recentSearches.length>0&&!e||s.length>0&&!e||null!==a&&e||Boolean(n)&&!e&&(!this.hasAttribute("enable-recent-searches")||0===this.recentSearches.length)&&0===s.length)}formatSearchResult(e){if("string"==typeof e||"number"==typeof e)return String(e);if(e&&"object"==typeof e){const t=e;if("string"==typeof t.title)return t.title;if("string"==typeof t.label)return t.label}return String(e)}handleSearch(e){const t=(e??this.value).trim();t&&(this.dispatchEvent(new CustomEvent("db-search",{detail:{value:t},bubbles:!0,composed:!0})),this.hasAttribute("enable-recent-searches")&&(this.recentSearches=[t,...this.recentSearches.filter(e=>e!==t)].slice(0,10),this.saveRecentSearches(),this.updateDropdown()))}updateDropdown(){if(!this.dropdown)return;const s=this.shouldShowDropdown();if(this.dropdown.hidden=!s,this.classList.toggle("designbase-wc-search-bar--dropdown-open",s),!s)return this.dropdown.replaceChildren(),void this.detachDropdownPortal();this.dropdown.replaceChildren();const n=this.hasInputValue(),r=this.parseJsonArray("categories"),i=this.parseJsonArray("suggested-searches"),o=this.getAttribute("selected-category")||"",c=this.parseJsonArray("search-results"),h=this.getAttribute("empty-state-message"),d=a.includes(this.getAttribute("recent-searches-layout")||"vertical")&&this.getAttribute("recent-searches-layout")||"vertical";if(r.length>0){const e=document.createElement("div");e.className="designbase-wc-search-bar__categories",r.forEach(t=>{const s=document.createElement("db-chip");s.setAttribute("label",t),s.setAttribute("size","s"),s.setAttribute("variant",t===o?"primary":"default"),s.setAttribute("clickable",""),s.addEventListener("mousedown",e=>{e.preventDefault(),this.setAttribute("selected-category",t),this.dispatchEvent(new CustomEvent("db-category-change",{detail:{category:t},bubbles:!0,composed:!0})),this.updateDropdown()}),e.append(s)}),this.dropdown.append(e)}if(n&&this.hasAttribute("search-results")){const e=document.createElement("div");if(e.className="designbase-wc-search-bar__results",c.length>0){const t=document.createElement("ul");t.className="designbase-wc-search-bar__results-list",c.forEach((e,s)=>{const a=document.createElement("li");a.className="designbase-wc-search-bar__result-item",a.textContent=this.formatSearchResult(e),a.addEventListener("mousedown",t=>{t.preventDefault(),this.isFocused=!1,this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-search-result-click",{detail:{result:e,index:s},bubbles:!0,composed:!0}))}),t.append(a)}),e.append(t)}else{const t=document.createElement("div");t.className="designbase-wc-search-bar__results-empty",t.textContent="검색 결과가 없습니다.",e.append(t)}return this.dropdown.append(e),void this.attachDropdownPortal()}if(this.hasAttribute("enable-recent-searches")&&!n&&this.recentSearches.length>0){const s=document.createElement("div");s.className=`designbase-wc-search-bar__recent-searches designbase-wc-search-bar__recent-searches--${d}`;const a=document.createElement("div");a.className="designbase-wc-search-bar__recent-header";const n=document.createElement("span");n.className="designbase-wc-search-bar__recent-title",n.textContent="최근 검색어";const r=document.createElement("button");r.type="button",r.className="designbase-wc-search-bar__clear-all-button",r.setAttribute("aria-label","모든 최근 검색어 삭제"),r.textContent="전체 삭제",r.addEventListener("mousedown",e=>{e.preventDefault(),this.recentSearches=[];try{localStorage.removeItem(this.getRecentSearchesKey())}catch{}this.updateDropdown()}),a.append(n,r);const i=document.createElement("div");i.className="designbase-wc-search-bar__recent-list",this.recentSearches.forEach(s=>{const a=document.createElement("div");a.className="designbase-wc-search-bar__recent-item";const n=document.createElement("button");n.type="button",n.className="designbase-wc-search-bar__recent-search-button",n.textContent=s,n.addEventListener("mousedown",e=>{if(e.preventDefault(),!this.input)return;this.input.value=s,this.setAttribute("value",s),this.syncValueState(),this.syncPlaceholder(),this.handleSearch(s);const t={value:s};this.dispatchEvent(new CustomEvent("db-input",{detail:t,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:t,bubbles:!0,composed:!0})),this.isFocused=!1,this.updateDropdown()});const r=document.createElement("button");r.type="button",r.className="designbase-wc-search-bar__recent-remove-button",r.setAttribute("aria-label",`${s} 삭제`),r.append(t("close",e("s"))),r.addEventListener("mousedown",e=>{e.preventDefault(),this.recentSearches=this.recentSearches.filter(e=>e!==s),this.saveRecentSearches(),this.updateDropdown()}),a.append(n,r),i.append(a)}),s.append(a,i),this.dropdown.append(s)}if(i.length>0&&!n){const e=document.createElement("div");e.className="designbase-wc-search-bar__suggestions";const t=document.createElement("div");t.className="designbase-wc-search-bar__suggestions-header";const s=document.createElement("span");s.className="designbase-wc-search-bar__suggestions-title",s.textContent="추천 검색어",t.append(s);const a=document.createElement("div");a.className="designbase-wc-search-bar__suggestions-list",i.forEach((e,t)=>{const s=document.createElement("button");s.type="button",s.className=["designbase-wc-search-bar__suggestion-item",t===this.currentSuggestion&&"designbase-wc-search-bar__suggestion-item--active"].filter(Boolean).join(" "),s.textContent=e,s.addEventListener("mousedown",t=>{if(t.preventDefault(),!this.input)return;this.clearSuggestionInterval(),this.input.value=e,this.setAttribute("value",e),this.syncValueState(),this.syncPlaceholder(),this.handleSearch(e);const s={value:e};this.dispatchEvent(new CustomEvent("db-input",{detail:s,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:s,bubbles:!0,composed:!0})),this.isFocused=!1,this.updateDropdown()}),a.append(s)}),e.append(t,a),this.dropdown.append(e)}if(h&&!n&&(!this.hasAttribute("enable-recent-searches")||0===this.recentSearches.length)&&0===i.length){const e=document.createElement("div");e.className="designbase-wc-search-bar__empty-state",e.textContent=h,this.dropdown.append(e)}this.attachDropdownPortal()}render(){const e=this.getAttribute("size")||"m",a=this.hasAttribute("disabled"),n=this.hasAttribute("readonly"),r=this.hasAttribute("full-width"),i=this.hasAttribute("show-shortcut"),o=this.getAttribute("value")??this.getAttribute("default-value")??"",c=Boolean(o.trim()),h=this.getIconPx();this.className=["designbase-wc-search-bar",`designbase-wc-search-bar--${s.includes(e)?e:"m"}`,"pill"===this.getAttribute("appearance")&&"designbase-wc-search-bar--appearance-pill",a&&"designbase-wc-search-bar--disabled",n&&"designbase-wc-search-bar--readonly",r&&"designbase-wc-search-bar--full-width",c&&"designbase-wc-search-bar--has-value",this.shouldShowDropdown()&&"designbase-wc-search-bar--dropdown-open"].filter(Boolean).join(" "),this.setAttribute("role","search"),this.clearSuggestionInterval(),this.detachDropdownPortal(),this.replaceChildren();const d=document.createElement("div");d.className="designbase-wc-search-bar__container";const l=document.createElement("div");l.className="designbase-wc-search-bar__search-icon",l.setAttribute("aria-hidden","true"),l.append(t("search",h));const u=document.createElement("input");if(u.type="text",u.className="designbase-wc-search-bar__input",u.value=o,u.disabled=a,u.readOnly=n,u.setAttribute("aria-label","검색어 입력"),this.input=u,i){const t=document.createElement("db-badge");t.className="designbase-wc-search-bar__shortcut-badge",t.setAttribute("size","l"===e?"m":"s"),t.setAttribute("variant","secondary"),t.setAttribute("badge-style","text"),t.setAttribute("aria-hidden","true"),t.textContent=this.getAttribute("shortcut-label")||"⌘K",t.hidden=c||a||n,this.shortcutBadge=t,d.append(l,u,t)}else d.append(l,u);const b=document.createElement("button");b.type="button",b.className="designbase-wc-search-bar__clear-button",b.setAttribute("aria-label","검색어 지우기"),b.hidden=!c||a||n,b.append(t("close",h)),this.clearButton=b,d.append(b);const p=document.createElement("div");p.className="designbase-wc-search-bar__dropdown",p.hidden=!0,p.addEventListener("mousedown",e=>{e.preventDefault()}),this.dropdown=p,u.addEventListener("input",()=>{this.setAttribute("value",u.value),this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),this.syncSuggestionRolling();const e={value:u.value};this.dispatchEvent(new CustomEvent("db-input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:e,bubbles:!0,composed:!0}))}),u.addEventListener("keydown",e=>{"Enter"===e.key&&this.handleSearch()}),u.addEventListener("focus",()=>{this.isFocused=!0,this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),u.addEventListener("blur",()=>{this.isFocused=!1,this.blurTimer&&clearTimeout(this.blurTimer),this.updateDropdown(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),b.addEventListener("click",()=>{u.value="",this.setAttribute("value",""),this.syncValueState(),this.syncPlaceholder(),this.updateDropdown(),this.syncSuggestionRolling(),u.focus(),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0}));const e={value:""};this.dispatchEvent(new CustomEvent("db-input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:e,bubbles:!0,composed:!0}))}),this.append(d,p),this.syncIcons(),this.syncPlaceholder(),this.syncSuggestionRolling(),this.bindGlobalShortcut(),this.updateDropdown()}}customElements.get("db-search-bar")||customElements.define("db-search-bar",DbSearchBar);export{DbSearchBar};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e="designbase-wc-segment-control",t={bar:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="12" width="4" height="8"/><rect x="10" y="8" width="4" height="12"/><rect x="17" y="4" width="4" height="16"/></svg>',line:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 16 9 10 14 13 20 6"/></svg>',pie:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v10l8.66 5"/><circle cx="12" cy="12" r="10"/></svg>',donut:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3"/></svg>',radar:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 20 8 17 20 7 20 4 8"/></svg>'};class DbSegmentControl extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.indicatorEl=null,this.segmentButtons=[],this.focusedIndex=-1,this.boundKeyDown=e=>this.handleKeyDown(e),this.boundResize=()=>this.updateIndicator(),this.resizeObserver=null}static get observedAttributes(){return["options","value","default-value","size","variant","appearance","full-width","disabled"]}connectedCallback(){this.built||(this.built=!0),this.render(),this.addEventListener("keydown",this.boundKeyDown),window.addEventListener("resize",this.boundResize),this.resizeObserver=new ResizeObserver(()=>this.updateIndicator()),this.resizeObserver.observe(this)}disconnectedCallback(){this.removeEventListener("keydown",this.boundKeyDown),window.removeEventListener("resize",this.boundResize),this.resizeObserver?.disconnect(),this.resizeObserver=null}attributeChangedCallback(e){this.built&&("value"!==e?this.render():this.updateSelection())}get options(){return this.parseOptions(this.getAttribute("options"))}set options(e){
|
|
1
|
+
const e="designbase-wc-segment-control",t={bar:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="12" width="4" height="8"/><rect x="10" y="8" width="4" height="12"/><rect x="17" y="4" width="4" height="16"/></svg>',line:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 16 9 10 14 13 20 6"/></svg>',pie:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v10l8.66 5"/><circle cx="12" cy="12" r="10"/></svg>',donut:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3"/></svg>',radar:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 20 8 17 20 7 20 4 8"/></svg>'};class DbSegmentControl extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.indicatorEl=null,this.segmentButtons=[],this.focusedIndex=-1,this.boundKeyDown=e=>this.handleKeyDown(e),this.boundResize=()=>this.updateIndicator(),this.resizeObserver=null}static get observedAttributes(){return["options","value","default-value","size","variant","appearance","full-width","disabled"]}connectedCallback(){this.built||(this.built=!0),this.render(),this.addEventListener("keydown",this.boundKeyDown),window.addEventListener("resize",this.boundResize),this.resizeObserver=new ResizeObserver(()=>this.updateIndicator()),this.resizeObserver.observe(this)}disconnectedCallback(){this.removeEventListener("keydown",this.boundKeyDown),window.removeEventListener("resize",this.boundResize),this.resizeObserver?.disconnect(),this.resizeObserver=null}attributeChangedCallback(e){this.built&&("value"!==e?this.render():this.updateSelection())}get options(){return this.parseOptions(this.getAttribute("options"))}set options(e){const t="string"==typeof e?e:JSON.stringify(e);this.getAttribute("options")!==t&&this.setAttribute("options",t)}get value(){return this.getAttribute("value")||this.getAttribute("default-value")||this.options[0]?.value||""}set value(e){this.setAttribute("value",e)}parseOptions(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}render(){const i=this.getAttribute("size")||"m",s=this.getAttribute("variant")||"default",n=this.getAttribute("appearance")||"default",r=this.hasAttribute("disabled"),o=this.options,a=this.value;this.className=[e,`${e}--${i}`,`${e}--${s}`,"pill"===n&&`${e}--appearance-pill`,"rounded"===n&&`${e}--appearance-rounded`,this.hasAttribute("full-width")&&`${e}--full-width`,r&&`${e}--disabled`].filter(Boolean).join(" "),this.setAttribute("role","tablist"),this.setAttribute("aria-label","세그먼트 컨트롤"),this.replaceChildren(),this.segmentButtons=[],o.forEach((i,n)=>{const o=i.value===a,l=Boolean(r||i.disabled),d=document.createElement("button");if(d.type="button",d.className=[`${e}__segment`,o&&`${e}__segment--selected`,l&&`${e}__segment--disabled`].filter(Boolean).join(" "),d.setAttribute("role","tab"),d.setAttribute("aria-selected",String(o)),d.setAttribute("aria-disabled",String(l)),d.setAttribute("tabindex",o?"0":"-1"),d.disabled=l,i.icon&&t[i.icon]){const s=document.createElement("span");s.className=`${e}__segment-icon`,s.innerHTML=t[i.icon],d.appendChild(s)}const h=document.createElement("span");h.className=`${e}__segment-label`,h.textContent=i.label,"icon-only"===s&&h.setAttribute("aria-label",i.label),d.appendChild(h),d.addEventListener("click",()=>this.select(i.value)),d.addEventListener("focus",()=>{this.focusedIndex=n,d.classList.add(`${e}__segment--focused`)}),d.addEventListener("blur",()=>{this.focusedIndex=-1,d.classList.remove(`${e}__segment--focused`)}),this.appendChild(d),this.segmentButtons.push(d)}),this.indicatorEl=document.createElement("div"),this.indicatorEl.className=`${e}__indicator`,this.appendChild(this.indicatorEl),this.updateSelection()}updateSelection(){const t=this.options,i=this.value,s=t.findIndex(e=>e.value===i);this.segmentButtons.forEach((s,n)=>{const r=t[n],o=r?.value===i;s.classList.toggle(`${e}__segment--selected`,o),s.setAttribute("aria-selected",String(o)),s.setAttribute("tabindex",o?"0":"-1")}),this.indicatorEl&&t.length>0&&s>=0&&requestAnimationFrame(()=>this.updateIndicator())}updateIndicator(){const e=this.options.findIndex(e=>e.value===this.value),t=this.segmentButtons[e];this.indicatorEl&&t&&(this.indicatorEl.style.width=`${t.offsetWidth}px`,this.indicatorEl.style.transform=`translateX(${t.offsetLeft}px)`)}select(e){if(this.hasAttribute("disabled"))return;const t=this.options.find(t=>t.value===e);t&&!t.disabled&&(this.setAttribute("value",e),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e},bubbles:!0,composed:!0})))}handleKeyDown(e){if(this.hasAttribute("disabled"))return;const t=this.options,i=t.findIndex(e=>e.value===this.value);if(-1===i)return;let s=i;switch(e.key){case"ArrowLeft":e.preventDefault(),s=i>0?i-1:t.length-1;break;case"ArrowRight":e.preventDefault(),s=i<t.length-1?i+1:0;break;case"Home":e.preventDefault(),s=0;break;case"End":e.preventDefault(),s=t.length-1;break;case"Enter":case" ":return e.preventDefault(),void this.select(t[s]?.value??this.value);default:return}for(;s!==i;){const i=t[s];if(i&&!i.disabled){this.segmentButtons[s]?.focus();break}s="ArrowLeft"===e.key||"Home"===e.key?s>0?s-1:t.length-1:s<t.length-1?s+1:0}}}customElements.get("db-segment-control")||customElements.define("db-segment-control",DbSegmentControl);export{DbSegmentControl};
|