1+ import { showPopup , ValueType , w3color } from "@node-projects/web-component-designer" ;
2+ import "@node-projects/pickr-webcomponent" ;
3+ import { BaseCustomWebComponentConstructorAppend } from "@node-projects/base-custom-webcomponent" ;
4+
5+ type PickrRgba = [ number , number , number , number ] & {
6+ toString : ( precision ?: number ) => string ;
7+ } ;
8+
9+ type PickrColor = {
10+ toRGBA ( ) : PickrRgba ;
11+ } ;
12+
13+ type PickrSaveEvent = CustomEvent < {
14+ value : PickrColor | null ;
15+ } > ;
16+
17+ type PickrElement = HTMLElement & {
18+ config : {
19+ default ?: string ;
20+ swatches ?: string [ ] ;
21+ components ?: {
22+ preview ?: boolean ;
23+ opacity ?: boolean ;
24+ hue ?: boolean ;
25+ interaction ?: {
26+ hex ?: boolean ;
27+ rgba ?: boolean ;
28+ hsla ?: boolean ;
29+ hsva ?: boolean ;
30+ input ?: boolean ;
31+ cancel ?: boolean ;
32+ save ?: boolean ;
33+ } ;
34+ } ;
35+ } ;
36+ setColor ( value : string | null , silent ?: boolean ) : boolean ;
37+ } ;
38+
39+ export class DemoColorEditor extends BaseCustomWebComponentConstructorAppend {
40+ private static readonly _defaultColor = '#000000' ;
41+
42+ private _colorValue : string | null = null ;
43+ private _valueLabel : HTMLSpanElement ;
44+ private _swatchFill : HTMLSpanElement ;
45+ private static _closePopup ?: ( ) => void ;
46+
47+ constructor ( private changedCallback : ( newValue : any ) => void ) {
48+ super ( ) ;
49+
50+ const element = document . createElement ( 'button' ) ;
51+ element . type = 'button' ;
52+ element . style . display = 'grid' ;
53+ element . style . gridTemplateColumns = '18px minmax(0, 1fr)' ;
54+ element . style . alignItems = 'center' ;
55+ element . style . gap = '8px' ;
56+ element . style . width = '100%' ;
57+ element . style . minHeight = '24px' ;
58+ element . style . padding = '2px 6px' ;
59+ element . style . border = '1px solid var(--input-border-color, #596c7a)' ;
60+ element . style . background = 'transparent' ;
61+ element . style . color = 'inherit' ;
62+ //element.style.cursor = property.readonly ? 'default' : 'pointer';
63+ element . style . textAlign = 'left' ;
64+
65+ const swatch = document . createElement ( 'span' ) ;
66+ swatch . style . position = 'relative' ;
67+ swatch . style . display = 'block' ;
68+ swatch . style . width = '16px' ;
69+ swatch . style . height = '16px' ;
70+ swatch . style . borderRadius = '3px' ;
71+ swatch . style . overflow = 'hidden' ;
72+ swatch . style . border = '1px solid gray' ;
73+
74+ this . _swatchFill = document . createElement ( 'span' ) ;
75+ this . _swatchFill . style . position = 'absolute' ;
76+ this . _swatchFill . style . inset = '0' ;
77+ swatch . appendChild ( this . _swatchFill ) ;
78+
79+ this . _valueLabel = document . createElement ( 'span' ) ;
80+ this . _valueLabel . style . overflow = 'hidden' ;
81+ this . _valueLabel . style . textOverflow = 'ellipsis' ;
82+ this . _valueLabel . style . whiteSpace = 'nowrap' ;
83+
84+ element . append ( swatch , this . _valueLabel ) ;
85+
86+ //if (property.readonly)
87+ // element.disabled = true;
88+ //else
89+ element . onclick = ( ) => { void this . _openPopup ( ) ; } ;
90+
91+ this . shadowRoot . appendChild ( element ) ;
92+ this . _applyDisplayValue ( null ) ;
93+ }
94+
95+ refreshValue ( valueType : ValueType , value : any ) {
96+ this . _colorValue = value ? String ( value ) : null ;
97+ this . _applyDisplayValue ( this . _colorValue ) ;
98+ }
99+
100+ private async _openPopup ( ) {
101+ const pickrElement = this . ownerDocument . createElement ( 'pickr-classic' ) as PickrElement ;
102+ pickrElement . config = {
103+ default : this . _colorValue ?? DemoColorEditor . _defaultColor ,
104+ components : {
105+ preview : true ,
106+ opacity : true ,
107+ hue : true ,
108+ interaction : {
109+ hex : true ,
110+ rgba : true ,
111+ hsla : true ,
112+ hsva : true ,
113+ input : true ,
114+ cancel : true ,
115+ save : true
116+ }
117+ }
118+ } ;
119+
120+ //pickrElement.setColor(this._colorValue ?? TsColorPropertyEditor._defaultColor, true);
121+ pickrElement . addEventListener ( 'save' , ( event ) => void this . _handlePickrSave ( event as PickrSaveEvent ) ) ;
122+ pickrElement . addEventListener ( 'cancel' , ( ) => { void this . _closePopup ( true ) ; } ) ;
123+
124+ DemoColorEditor . _closePopup = showPopup ( pickrElement , this , ( ) => { void this . _closePopup ( true ) ; } ) ;
125+ }
126+
127+ private async _handlePickrSave ( event : PickrSaveEvent ) {
128+ let nextValue
129+ if ( event . detail . value !== null ) {
130+ nextValue = this . _formatColor ( event . detail . value ) ;
131+ }
132+ this . _colorValue = < any > nextValue ;
133+ this . _applyDisplayValue ( nextValue ! ) ;
134+ this . changedCallback ( nextValue ) ;
135+ await this . _closePopup ( false ) ;
136+ }
137+
138+ public get value ( ) {
139+ return this . _colorValue ;
140+ }
141+ public set value ( v : string | null ) {
142+ this . _colorValue = v ;
143+ this . _applyDisplayValue ( v ) ;
144+ }
145+
146+ private async _closePopup ( removePreview : boolean ) {
147+ DemoColorEditor . _closePopup ?.( ) ;
148+ DemoColorEditor . _closePopup = undefined ;
149+ }
150+
151+
152+ private _applyDisplayValue ( value : string | null ) {
153+ const displayValue = value ?? DemoColorEditor . _defaultColor ;
154+ this . _valueLabel . textContent = value ?? DemoColorEditor . _defaultColor ;
155+ this . _valueLabel . title = value ?? DemoColorEditor . _defaultColor ;
156+ this . _swatchFill . style . background = displayValue ;
157+ }
158+
159+ private _formatColor ( color : PickrColor ) {
160+ const rgba = color . toRGBA ( ) ;
161+ if ( rgba [ 3 ] < 0.999 )
162+ return rgba . toString ( 3 ) ;
163+ try {
164+ return w3color . toColorObject ( rgba . toString ( ) ) . toNameOrHexString ( ) ;
165+ } catch {
166+ return rgba . toString ( ) ;
167+ }
168+ }
169+ }
170+ customElements . define ( 'demo-color-editor' , DemoColorEditor ) ;
0 commit comments