@substrate-system/color-picker 0.0.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/LICENSE +21 -0
- package/README.md +182 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +195 -0
- package/dist/index.js.map +7 -0
- package/dist/index.min.js +14 -0
- package/dist/index.min.js.map +7 -0
- package/dist/meta.json +46 -0
- package/dist/style.css +24 -0
- package/dist/style.css.map +1 -0
- package/dist/style.min.css +2 -0
- package/dist/style.min.css.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 - 2021 Simon Reinisch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# color-picker
|
|
2
|
+
[](https://github.com/substrate-system/color-picker/actions/workflows/nodejs.yml)
|
|
3
|
+
[](README.md)
|
|
4
|
+
[](README.md)
|
|
5
|
+
[](https://semver.org/)
|
|
6
|
+
[](./CHANGELOG.md)
|
|
7
|
+
[](https://packagephobia.com/result?p=@substrate-system/color-picker)
|
|
8
|
+
[](https://bundlephobia.com/package/@substrate-system/color-picker)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
Color picker web component.
|
|
12
|
+
|
|
13
|
+
This was originally forked from [Simonwep/pickr](https://github.com/Simonwep/pickr).
|
|
14
|
+
|
|
15
|
+
[See a live demo](https://substrate-system.github.io/color-picker/)
|
|
16
|
+
|
|
17
|
+
<details><summary><h2>Contents</h2></summary>
|
|
18
|
+
|
|
19
|
+
<!-- toc -->
|
|
20
|
+
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Example](#example)
|
|
23
|
+
* [JS](#js)
|
|
24
|
+
* [HTML](#html)
|
|
25
|
+
- [API](#api)
|
|
26
|
+
* [Properties](#properties)
|
|
27
|
+
* [Events](#events)
|
|
28
|
+
* [Keyboard navigation](#keyboard-navigation)
|
|
29
|
+
- [Modules](#modules)
|
|
30
|
+
* [ESM](#esm)
|
|
31
|
+
* [Common JS](#common-js)
|
|
32
|
+
- [CSS](#css)
|
|
33
|
+
* [Import CSS](#import-css)
|
|
34
|
+
* [Customize CSS](#customize-css)
|
|
35
|
+
* [Pre-built JS](#pre-built-js)
|
|
36
|
+
|
|
37
|
+
<!-- tocstop -->
|
|
38
|
+
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
npm i -S @substrate-system/color-picker
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Example
|
|
48
|
+
|
|
49
|
+
It registers itself under the name `color-picker`. Just import, then you can
|
|
50
|
+
use the tag in HTML. Set `swatches` to an array of valid CSS color strings.
|
|
51
|
+
|
|
52
|
+
### JS
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import '@substrate-system/color-picker'
|
|
56
|
+
|
|
57
|
+
const picker = document.querySelector('color-picker')
|
|
58
|
+
|
|
59
|
+
picker.swatches = ['#000', '#fff', '#ef4444', '#3b82f6']
|
|
60
|
+
picker.value = '#000'
|
|
61
|
+
|
|
62
|
+
picker.addEventListener('change', (ev) => {
|
|
63
|
+
console.log(ev.detail.value) // selected color string
|
|
64
|
+
console.log(ev.detail.index) // index into swatches array
|
|
65
|
+
console.log(ev.detail.source) // 'pointer' | 'keyboard' | 'programmatic'
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### HTML
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<color-picker id="picker"></color-picker>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API
|
|
76
|
+
|
|
77
|
+
### Properties
|
|
78
|
+
|
|
79
|
+
| Property | Type | Description |
|
|
80
|
+
|------------|-----------------|--------------------------------------|
|
|
81
|
+
| `swatches` | `string[]` | Array of valid CSS color values. |
|
|
82
|
+
| `value` | `string\|null` | The currently selected color string. |
|
|
83
|
+
| `disabled` | `boolean` | Disables all interaction. |
|
|
84
|
+
|
|
85
|
+
You can also set `value` via an HTML attribute:
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<color-picker value="#ef4444"></color-picker>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Events
|
|
92
|
+
|
|
93
|
+
#### `change`
|
|
94
|
+
|
|
95
|
+
Fired when the selected color changes.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
interface ChangeDetail {
|
|
99
|
+
value:string | null
|
|
100
|
+
index:number | null
|
|
101
|
+
source:'pointer' | 'keyboard' | 'programmatic'
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Keyboard navigation
|
|
106
|
+
|
|
107
|
+
When a swatch has focus:
|
|
108
|
+
|
|
109
|
+
| Key | Action |
|
|
110
|
+
|---------------------------------|----------------------------|
|
|
111
|
+
| `ArrowRight` / `ArrowDown` | Select next swatch |
|
|
112
|
+
| `ArrowLeft` / `ArrowUp` | Select previous swatch |
|
|
113
|
+
| `Space` / `Enter` | Confirm active swatch |
|
|
114
|
+
|
|
115
|
+
## Modules
|
|
116
|
+
|
|
117
|
+
This exposes ESM and Common JS via the
|
|
118
|
+
[package.json `exports` field](https://nodejs.org/api/packages.html#exports).
|
|
119
|
+
|
|
120
|
+
### ESM
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import { registerColorPicker } from '@substrate-system/color-picker'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Or import just the component class:
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
import { ColorPicker } from '@substrate-system/color-picker'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Common JS
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
const { registerColorPicker } = require('@substrate-system/color-picker')
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## CSS
|
|
139
|
+
|
|
140
|
+
### Import CSS
|
|
141
|
+
|
|
142
|
+
The component bundles its own styles. If you need to import them separately:
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
import '@substrate-system/color-picker/css'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Or minified:
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import '@substrate-system/color-picker/css/min'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Customize CSS
|
|
155
|
+
|
|
156
|
+
Override styles on the `color-picker` element:
|
|
157
|
+
|
|
158
|
+
```css
|
|
159
|
+
color-picker .swatch {
|
|
160
|
+
width: 32px;
|
|
161
|
+
height: 32px;
|
|
162
|
+
border-radius: 4px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
color-picker .swatch[aria-checked='true'] {
|
|
166
|
+
border-color: hotpink;
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Pre-built JS
|
|
171
|
+
|
|
172
|
+
Copy the minified bundle to your web server:
|
|
173
|
+
|
|
174
|
+
```sh
|
|
175
|
+
cp ./node_modules/@substrate-system/color-picker/dist/index.min.js ./public
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Then reference it in HTML:
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<script type="module" src="./index.min.js"></script>
|
|
182
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { WebComponent } from '@substrate-system/web-component';
|
|
2
|
+
import './index.css';
|
|
3
|
+
type InteractionSource = 'pointer' | 'keyboard' | 'programmatic';
|
|
4
|
+
export interface ChangeDetail {
|
|
5
|
+
value: string | null;
|
|
6
|
+
index: number | null;
|
|
7
|
+
source: InteractionSource;
|
|
8
|
+
}
|
|
9
|
+
export type ChangeEvent = CustomEvent<ChangeDetail>;
|
|
10
|
+
declare global {
|
|
11
|
+
interface HTMLElementTagNameMap {
|
|
12
|
+
'color-picker': ColorPicker;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
declare const ColorPicker_base: typeof WebComponent & {
|
|
16
|
+
new (...args: any[]): WebComponent;
|
|
17
|
+
TAG: string;
|
|
18
|
+
define: typeof WebComponent.define;
|
|
19
|
+
event: typeof WebComponent.event;
|
|
20
|
+
};
|
|
21
|
+
export declare class ColorPicker extends ColorPicker_base {
|
|
22
|
+
static observedAttributes: string[];
|
|
23
|
+
private _swatches;
|
|
24
|
+
private _state;
|
|
25
|
+
get swatches(): string[];
|
|
26
|
+
set swatches(values: string[]);
|
|
27
|
+
get value(): string | null;
|
|
28
|
+
set value(nextValue: string | null);
|
|
29
|
+
get disabled(): boolean;
|
|
30
|
+
set disabled(isDisabled: boolean);
|
|
31
|
+
connectedCallback(): void;
|
|
32
|
+
handleChange_value(_oldValue: string, newValue: string): void;
|
|
33
|
+
setSwatches(swatches: string[]): void;
|
|
34
|
+
selectByIndex(index: number, source?: InteractionSource): void;
|
|
35
|
+
getValue(): string | null;
|
|
36
|
+
private onSwatchKeydown;
|
|
37
|
+
private onSwatchClick;
|
|
38
|
+
render(): void;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAE9D,OAAO,aAAa,CAAA;AAEpB,KAAK,iBAAiB,GAAG,SAAS,GAAC,UAAU,GAAC,cAAc,CAAA;AAE5D,MAAM,WAAW,YAAY;IACzB,KAAK,EAAC,MAAM,GAAC,IAAI,CAAA;IACjB,KAAK,EAAC,MAAM,GAAC,IAAI,CAAA;IACjB,MAAM,EAAC,iBAAiB,CAAA;CAC3B;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,CAAA;AAsBnD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,cAAc,EAAC,WAAW,CAAA;KAC7B;CACJ;;;;;;;AAED,qBAAa,WAAY,SAAQ,gBAAmC;IAChE,MAAM,CAAC,kBAAkB,WAAsC;IAE/D,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,MAAM,CAA+C;IAE7D,IAAI,QAAQ,IAAI,MAAM,EAAE,CAEvB;IAED,IAAI,QAAQ,CAAE,MAAM,EAAC,MAAM,EAAE,EAwB5B;IAED,IAAI,KAAK,IAAI,MAAM,GAAC,IAAI,CAEvB;IAED,IAAI,KAAK,CAAE,SAAS,EAAC,MAAM,GAAC,IAAI,EAY/B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,QAAQ,CAAE,UAAU,EAAC,OAAO,EAO/B;IAED,iBAAiB,IAAI,IAAI;IAMzB,kBAAkB,CAAE,SAAS,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,GAAE,IAAI;IAK3D,WAAW,CAAE,QAAQ,EAAC,MAAM,EAAE,GAAE,IAAI;IAIpC,aAAa,CAAE,KAAK,EAAC,MAAM,EAAE,MAAM,GAAC,iBAAkC,GAAE,IAAI;IAqB5E,QAAQ,IAAI,MAAM,GAAC,IAAI;IAIvB,OAAO,CAAC,eAAe,CAqBtB;IAED,OAAO,CAAC,aAAa,CAKpB;IAED,MAAM,IAAI,IAAI;CAgCjB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { WebComponent } from "@substrate-system/web-component";
|
|
4
|
+
import { define } from "@substrate-system/web-component/util";
|
|
5
|
+
import "./index.css";
|
|
6
|
+
const DEFAULT_SWATCHES = [
|
|
7
|
+
"#000000",
|
|
8
|
+
"#f8fafc",
|
|
9
|
+
"#ef4444",
|
|
10
|
+
"#f97316",
|
|
11
|
+
"#eab308",
|
|
12
|
+
"#22c55e",
|
|
13
|
+
"#3b82f6",
|
|
14
|
+
"#8b5cf6",
|
|
15
|
+
"#ec4899"
|
|
16
|
+
];
|
|
17
|
+
class ColorPicker extends WebComponent.create("color-picker") {
|
|
18
|
+
static {
|
|
19
|
+
__name(this, "ColorPicker");
|
|
20
|
+
}
|
|
21
|
+
static observedAttributes = ["value", "disabled", "aria-label"];
|
|
22
|
+
_swatches = [...DEFAULT_SWATCHES];
|
|
23
|
+
_state = createSelectionState(0, DEFAULT_SWATCHES[0]);
|
|
24
|
+
get swatches() {
|
|
25
|
+
return [...this._swatches];
|
|
26
|
+
}
|
|
27
|
+
set swatches(values) {
|
|
28
|
+
const sanitized = sanitizeSwatches(values);
|
|
29
|
+
if (sanitized.length !== values.length) {
|
|
30
|
+
console.warn("color-picker: invalid CSS color values were ignored");
|
|
31
|
+
}
|
|
32
|
+
this._swatches = sanitized;
|
|
33
|
+
if (this._swatches.length === 0) {
|
|
34
|
+
this._state = createSelectionState();
|
|
35
|
+
this.render();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (this._state.selectedIndex == null || this._state.selectedIndex >= this._swatches.length || this._state.selectedValue !== this._swatches[this._state.selectedIndex]) {
|
|
39
|
+
this.selectByIndex(0, "programmatic");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.render();
|
|
43
|
+
}
|
|
44
|
+
get value() {
|
|
45
|
+
return this._state.selectedValue;
|
|
46
|
+
}
|
|
47
|
+
set value(nextValue) {
|
|
48
|
+
if (nextValue == null) {
|
|
49
|
+
this._state.selectedIndex = null;
|
|
50
|
+
this._state.selectedValue = null;
|
|
51
|
+
this._state.activeIndex = null;
|
|
52
|
+
this.render();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const idx = this._swatches.findIndex((entry) => entry === nextValue);
|
|
56
|
+
if (idx === -1) return;
|
|
57
|
+
this.selectByIndex(idx, "programmatic");
|
|
58
|
+
}
|
|
59
|
+
get disabled() {
|
|
60
|
+
return this.hasAttribute("disabled");
|
|
61
|
+
}
|
|
62
|
+
set disabled(isDisabled) {
|
|
63
|
+
if (isDisabled) {
|
|
64
|
+
this.setAttribute("disabled", "");
|
|
65
|
+
} else {
|
|
66
|
+
this.removeAttribute("disabled");
|
|
67
|
+
}
|
|
68
|
+
this.render();
|
|
69
|
+
}
|
|
70
|
+
connectedCallback() {
|
|
71
|
+
super.connectedCallback();
|
|
72
|
+
this.setAttribute("role", "radiogroup");
|
|
73
|
+
this.render();
|
|
74
|
+
}
|
|
75
|
+
handleChange_value(_oldValue, newValue) {
|
|
76
|
+
if (!newValue || !isValidCssColor(newValue)) return;
|
|
77
|
+
this.value = newValue;
|
|
78
|
+
}
|
|
79
|
+
setSwatches(swatches) {
|
|
80
|
+
this.swatches = swatches;
|
|
81
|
+
}
|
|
82
|
+
selectByIndex(index, source = "programmatic") {
|
|
83
|
+
if (this._swatches.length === 0) return;
|
|
84
|
+
const max = this._swatches.length - 1;
|
|
85
|
+
const normalized = clampIndex(index, max);
|
|
86
|
+
if (normalized < 0 || normalized > max) return;
|
|
87
|
+
this._state.selectedIndex = normalized;
|
|
88
|
+
this._state.activeIndex = normalized;
|
|
89
|
+
this._state.selectedValue = this._swatches[normalized];
|
|
90
|
+
this._state.lastInteraction = source;
|
|
91
|
+
this.render();
|
|
92
|
+
this.emit("change", {
|
|
93
|
+
detail: {
|
|
94
|
+
value: this._state.selectedValue,
|
|
95
|
+
index: this._state.selectedIndex,
|
|
96
|
+
source
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
getValue() {
|
|
101
|
+
return this._state.selectedValue;
|
|
102
|
+
}
|
|
103
|
+
onSwatchKeydown = /* @__PURE__ */ __name((ev) => {
|
|
104
|
+
if (this._swatches.length === 0 || this.disabled) return;
|
|
105
|
+
const current = this._state.activeIndex ?? 0;
|
|
106
|
+
const max = this._swatches.length - 1;
|
|
107
|
+
if (ev.key === "ArrowRight" || ev.key === "ArrowDown") {
|
|
108
|
+
ev.preventDefault();
|
|
109
|
+
this.selectByIndex(nextIndex(current, 1, max), "keyboard");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (ev.key === "ArrowLeft" || ev.key === "ArrowUp") {
|
|
113
|
+
ev.preventDefault();
|
|
114
|
+
this.selectByIndex(nextIndex(current, -1, max), "keyboard");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (ev.key === " " || ev.key === "Enter") {
|
|
118
|
+
ev.preventDefault();
|
|
119
|
+
this.selectByIndex(current, "keyboard");
|
|
120
|
+
}
|
|
121
|
+
}, "onSwatchKeydown");
|
|
122
|
+
onSwatchClick = /* @__PURE__ */ __name((ev) => {
|
|
123
|
+
if (this.disabled) return;
|
|
124
|
+
const target = ev.currentTarget;
|
|
125
|
+
const idx = Number(target.dataset.index);
|
|
126
|
+
this.selectByIndex(idx, "pointer");
|
|
127
|
+
}, "onSwatchClick");
|
|
128
|
+
render() {
|
|
129
|
+
this.setAttribute("role", "radiogroup");
|
|
130
|
+
const label = this.getAttribute("aria-label") ?? "Color swatches";
|
|
131
|
+
this.setAttribute("aria-label", label);
|
|
132
|
+
const swatchesHtml = this._swatches.map((value, index) => {
|
|
133
|
+
const checked = this._state.selectedIndex === index;
|
|
134
|
+
const active = this._state.activeIndex === index;
|
|
135
|
+
return `
|
|
136
|
+
<button
|
|
137
|
+
type="button"
|
|
138
|
+
class="swatch${active ? " is-active" : ""}"
|
|
139
|
+
role="radio"
|
|
140
|
+
aria-label="${value}"
|
|
141
|
+
aria-checked="${checked ? "true" : "false"}"
|
|
142
|
+
data-index="${index}"
|
|
143
|
+
data-value="${value}"
|
|
144
|
+
style="background:${value};"
|
|
145
|
+
${this.disabled ? "disabled" : ""}
|
|
146
|
+
></button>
|
|
147
|
+
`;
|
|
148
|
+
}).join("");
|
|
149
|
+
this.innerHTML = `<div class="picker">${swatchesHtml}</div>`;
|
|
150
|
+
this.querySelectorAll(".swatch").forEach((swatch) => {
|
|
151
|
+
swatch.addEventListener("click", this.onSwatchClick);
|
|
152
|
+
swatch.addEventListener("keydown", this.onSwatchKeydown);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
define(ColorPicker.TAG, ColorPicker);
|
|
157
|
+
function isValidCssColor(value) {
|
|
158
|
+
if (!value || typeof value !== "string") return false;
|
|
159
|
+
const option = new Option();
|
|
160
|
+
option.style.color = "";
|
|
161
|
+
option.style.color = value;
|
|
162
|
+
return option.style.color !== "";
|
|
163
|
+
}
|
|
164
|
+
__name(isValidCssColor, "isValidCssColor");
|
|
165
|
+
function sanitizeSwatches(swatches) {
|
|
166
|
+
return swatches.filter(isValidCssColor);
|
|
167
|
+
}
|
|
168
|
+
__name(sanitizeSwatches, "sanitizeSwatches");
|
|
169
|
+
function createSelectionState(selectedIndex = null, selectedValue = null) {
|
|
170
|
+
return {
|
|
171
|
+
activeIndex: selectedIndex,
|
|
172
|
+
selectedIndex,
|
|
173
|
+
selectedValue,
|
|
174
|
+
lastInteraction: null
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
__name(createSelectionState, "createSelectionState");
|
|
178
|
+
function clampIndex(index, max) {
|
|
179
|
+
if (max < 0) return -1;
|
|
180
|
+
if (index < 0) return 0;
|
|
181
|
+
if (index > max) return max;
|
|
182
|
+
return index;
|
|
183
|
+
}
|
|
184
|
+
__name(clampIndex, "clampIndex");
|
|
185
|
+
function nextIndex(current, delta, max) {
|
|
186
|
+
const raw = current + delta;
|
|
187
|
+
if (raw < 0) return max;
|
|
188
|
+
if (raw > max) return 0;
|
|
189
|
+
return raw;
|
|
190
|
+
}
|
|
191
|
+
__name(nextIndex, "nextIndex");
|
|
192
|
+
export {
|
|
193
|
+
ColorPicker
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { WebComponent } from '@substrate-system/web-component'\nimport { define } from '@substrate-system/web-component/util'\nimport './index.css'\n\ntype InteractionSource = 'pointer'|'keyboard'|'programmatic'\n\nexport interface ChangeDetail {\n value:string|null\n index:number|null\n source:InteractionSource\n}\n\nexport type ChangeEvent = CustomEvent<ChangeDetail>\n\ninterface SelectionState {\n activeIndex:number|null\n selectedIndex:number|null\n selectedValue:string|null\n lastInteraction:InteractionSource|null\n}\n\nconst DEFAULT_SWATCHES = [\n '#000000',\n '#f8fafc',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#22c55e',\n '#3b82f6',\n '#8b5cf6',\n '#ec4899'\n]\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'color-picker':ColorPicker\n }\n}\n\nexport class ColorPicker extends WebComponent.create('color-picker') {\n static observedAttributes = ['value', 'disabled', 'aria-label']\n\n private _swatches:string[] = [...DEFAULT_SWATCHES]\n private _state = createSelectionState(0, DEFAULT_SWATCHES[0])\n\n get swatches ():string[] {\n return [...this._swatches]\n }\n\n set swatches (values:string[]) {\n const sanitized = sanitizeSwatches(values)\n if (sanitized.length !== values.length) {\n console.warn('color-picker: invalid CSS color values were ignored')\n }\n\n this._swatches = sanitized\n\n if (this._swatches.length === 0) {\n this._state = createSelectionState()\n this.render()\n return\n }\n\n if (\n this._state.selectedIndex == null ||\n this._state.selectedIndex >= this._swatches.length ||\n this._state.selectedValue !== this._swatches[this._state.selectedIndex]\n ) {\n this.selectByIndex(0, 'programmatic')\n return\n }\n\n this.render()\n }\n\n get value ():string|null {\n return this._state.selectedValue\n }\n\n set value (nextValue:string|null) {\n if (nextValue == null) {\n this._state.selectedIndex = null\n this._state.selectedValue = null\n this._state.activeIndex = null\n this.render()\n return\n }\n\n const idx = this._swatches.findIndex((entry) => entry === nextValue)\n if (idx === -1) return\n this.selectByIndex(idx, 'programmatic')\n }\n\n get disabled ():boolean {\n return this.hasAttribute('disabled')\n }\n\n set disabled (isDisabled:boolean) {\n if (isDisabled) {\n this.setAttribute('disabled', '')\n } else {\n this.removeAttribute('disabled')\n }\n this.render()\n }\n\n connectedCallback ():void {\n super.connectedCallback()\n this.setAttribute('role', 'radiogroup')\n this.render()\n }\n\n handleChange_value (_oldValue:string, newValue:string):void {\n if (!newValue || !isValidCssColor(newValue)) return\n this.value = newValue\n }\n\n setSwatches (swatches:string[]):void {\n this.swatches = swatches\n }\n\n selectByIndex (index:number, source:InteractionSource = 'programmatic'):void {\n if (this._swatches.length === 0) return\n const max = this._swatches.length - 1\n const normalized = clampIndex(index, max)\n if (normalized < 0 || normalized > max) return\n\n this._state.selectedIndex = normalized\n this._state.activeIndex = normalized\n this._state.selectedValue = this._swatches[normalized]\n this._state.lastInteraction = source\n this.render()\n\n this.emit<ChangeDetail>('change', {\n detail: {\n value: this._state.selectedValue,\n index: this._state.selectedIndex,\n source\n }\n })\n }\n\n getValue ():string|null {\n return this._state.selectedValue\n }\n\n private onSwatchKeydown = (ev:KeyboardEvent):void => {\n if (this._swatches.length === 0 || this.disabled) return\n const current = this._state.activeIndex ?? 0\n const max = this._swatches.length - 1\n\n if (ev.key === 'ArrowRight' || ev.key === 'ArrowDown') {\n ev.preventDefault()\n this.selectByIndex(nextIndex(current, 1, max), 'keyboard')\n return\n }\n\n if (ev.key === 'ArrowLeft' || ev.key === 'ArrowUp') {\n ev.preventDefault()\n this.selectByIndex(nextIndex(current, -1, max), 'keyboard')\n return\n }\n\n if (ev.key === ' ' || ev.key === 'Enter') {\n ev.preventDefault()\n this.selectByIndex(current, 'keyboard')\n }\n }\n\n private onSwatchClick = (ev:Event):void => {\n if (this.disabled) return\n const target = ev.currentTarget as HTMLElement\n const idx = Number(target.dataset.index)\n this.selectByIndex(idx, 'pointer')\n }\n\n render ():void {\n this.setAttribute('role', 'radiogroup')\n\n const label = this.getAttribute('aria-label') ?? 'Color swatches'\n this.setAttribute('aria-label', label)\n\n const swatchesHtml = this._swatches.map((value, index) => {\n const checked = this._state.selectedIndex === index\n const active = this._state.activeIndex === index\n\n return `\n <button\n type=\"button\"\n class=\"swatch${active ? ' is-active' : ''}\"\n role=\"radio\"\n aria-label=\"${value}\"\n aria-checked=\"${checked ? 'true' : 'false'}\"\n data-index=\"${index}\"\n data-value=\"${value}\"\n style=\"background:${value};\"\n ${this.disabled ? 'disabled' : ''}\n ></button>\n `\n }).join('')\n\n this.innerHTML = `<div class=\"picker\">${swatchesHtml}</div>`\n\n this.querySelectorAll<HTMLButtonElement>('.swatch').forEach((swatch) => {\n swatch.addEventListener('click', this.onSwatchClick)\n swatch.addEventListener('keydown', this.onSwatchKeydown)\n })\n }\n}\n\ndefine(ColorPicker.TAG, ColorPicker)\n\nfunction isValidCssColor (value:string):boolean {\n if (!value || typeof value !== 'string') return false\n const option = new Option()\n option.style.color = ''\n option.style.color = value\n return option.style.color !== ''\n}\n\nfunction sanitizeSwatches (swatches:string[]):string[] {\n return swatches.filter(isValidCssColor)\n}\n\nfunction createSelectionState (selectedIndex:number|null = null, selectedValue:string|null = null):SelectionState {\n return {\n activeIndex: selectedIndex,\n selectedIndex,\n selectedValue,\n lastInteraction: null\n }\n}\n\nfunction clampIndex (index:number, max:number):number {\n if (max < 0) return -1\n if (index < 0) return 0\n if (index > max) return max\n return index\n}\n\nfunction nextIndex (current:number, delta:number, max:number):number {\n const raw = current + delta\n if (raw < 0) return max\n if (raw > max) return 0\n return raw\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var A=Object.defineProperty;var s=(n,e)=>A(n,"name",{value:e,configurable:!0});var I=Object.defineProperty,S=s((n,e)=>I(n,"name",{value:e,configurable:!0}),"__name");function m(n){return Object.keys(n).reduce((e,t)=>{let r=n[t];return r?typeof r=="boolean"?r?(e+` ${t}`).trim():e:Array.isArray(r)?e+` ${t}="${r.join(" ")}"`:(e+` ${t}="${r}"`).trim():e},"")}s(m,"toAttributes");S(m,"toAttributes");var C=Object.defineProperty,d=s((n,e)=>C(n,"name",{value:e,configurable:!0}),"__name");function p(n){return document.createElement(n).constructor!==window.HTMLElement}s(p,"isRegistered");d(p,"isRegistered");function u(n,e){window&&"customElements"in window&&(p(n)||window.customElements.define(n,e))}s(u,"define");d(u,"define");var H=document.querySelector.bind(document),B=document.querySelectorAll.bind(document);function h(n,e){return n.matches||(n=n.parentElement),n.matches(e)?n:n.closest(e)}s(h,"match");d(h,"match");var k=Object.defineProperty,a=s((n,e)=>k(n,"name",{value:e,configurable:!0}),"__name"),c=class n extends window.HTMLElement{static{s(this,"WebComponent")}static{a(this,"WebComponent")}static TAG="";TAG="";static match(e){return h(e,this.TAG)}_globalWildcardListeners=new Set;_namespacedWildcardListeners=new Set;static create(e){let t=class extends n{static{s(this,"CreatedClass")}static{a(this,"CreatedClass")}static TAG=e;TAG=e;render(){throw new Error("`render` should be implemented by children")}};return t.define=function(){return n.define.call(this)},t.event=function(r){return n.event.call(this,r)},t}static define(){w(this.TAG,this)}async attributeChangedCallback(e,t,r){let i=this[`handleChange_${e}`];i&&await i.call(this,t,r)}addEventListener(e,t,r){e===n.event.call(this,"*")?this._namespacedWildcardListeners.add({listener:t,options:r}):e==="*"?t&&this._globalWildcardListeners.add({listener:t,options:r}):super.addEventListener(e,t,r)}_notifyNamespacedWildcardListeners(e){if(this._namespacedWildcardListeners.size===0)return;let t=this.TAG;!t||!e.type.startsWith(`${t}:`)||this._namespacedWildcardListeners.forEach(({listener:r})=>{try{typeof r=="function"?r.call(this,e):r&&typeof r.handleEvent=="function"&&r.handleEvent(e)}catch(i){console.error("Error in namespaced wildcard event listener:",i)}})}_notifyGlobalWildcardListeners(e){this._globalWildcardListeners.size!==0&&this._globalWildcardListeners.forEach(({listener:t})=>{try{typeof t=="function"?t.call(this,e):t&&typeof t.handleEvent=="function"&&t.handleEvent(e)}catch(r){console.error("Error in global wildcard event listener:",r)}})}connectedCallback(){this.render()}qs(e){return this.querySelector(e)}qsa(e){return this.querySelectorAll(e)}static event(e){return g(this.TAG,e)}emit(e,t={}){if(e==="*")throw new Error('Do not emit the literal "*"');let{bubbles:r=!0,cancelable:i=!0,detail:o}=t,f=`${this.TAG}:${e}`,b=new CustomEvent(f,{bubbles:r,cancelable:i,detail:o}),x=this.dispatchEvent(b);return this._notifyNamespacedWildcardListeners(b),x}dispatchEvent(e){let t=super.dispatchEvent(e);return this._notifyGlobalWildcardListeners(e),t}dispatch(e,t={}){let r=new CustomEvent(e,{bubbles:t.bubbles===void 0?!0:t.bubbles,cancelable:t.cancelable===void 0?!0:t.cancelable,detail:t.detail});return this.dispatchEvent(r)}on(e,t,r){let i=n.event.call(this,e);this.addEventListener(i,t,r)}removeEventListener(e,t,r){if(e===n.event.call(this,"*")){if(t&&this._namespacedWildcardListeners){for(let i of this._namespacedWildcardListeners)if(i.listener===t){this._namespacedWildcardListeners.delete(i);break}}}else if(e==="*"){if(t&&this._globalWildcardListeners){for(let i of this._globalWildcardListeners)if(i.listener===t){this._globalWildcardListeners.delete(i);break}}}else super.removeEventListener(e,t,r)}};function g(n,e){return`${n}:${e}`}s(g,"eventName");a(g,"eventName");function v(n){return document.createElement(n).constructor!==window.HTMLElement}s(v,"isRegistered");a(v,"isRegistered");function w(n,e){window&&"customElements"in window&&(v(n)||window.customElements.define(n,e))}s(w,"define");a(w,"define");var _=["#000000","#f8fafc","#ef4444","#f97316","#eab308","#22c55e","#3b82f6","#8b5cf6","#ec4899"],l=class extends c.create("color-picker"){static{s(this,"ColorPicker")}static observedAttributes=["value","disabled","aria-label"];_swatches=[..._];_state=y(0,_[0]);get swatches(){return[...this._swatches]}set swatches(e){let t=T(e);if(t.length!==e.length&&console.warn("color-picker: invalid CSS color values were ignored"),this._swatches=t,this._swatches.length===0){this._state=y(),this.render();return}if(this._state.selectedIndex==null||this._state.selectedIndex>=this._swatches.length||this._state.selectedValue!==this._swatches[this._state.selectedIndex]){this.selectByIndex(0,"programmatic");return}this.render()}get value(){return this._state.selectedValue}set value(e){if(e==null){this._state.selectedIndex=null,this._state.selectedValue=null,this._state.activeIndex=null,this.render();return}let t=this._swatches.findIndex(r=>r===e);t!==-1&&this.selectByIndex(t,"programmatic")}get disabled(){return this.hasAttribute("disabled")}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.render()}connectedCallback(){super.connectedCallback(),this.setAttribute("role","radiogroup"),this.render()}handleChange_value(e,t){!t||!L(t)||(this.value=t)}setSwatches(e){this.swatches=e}selectByIndex(e,t="programmatic"){if(this._swatches.length===0)return;let r=this._swatches.length-1,i=W(e,r);i<0||i>r||(this._state.selectedIndex=i,this._state.activeIndex=i,this._state.selectedValue=this._swatches[i],this._state.lastInteraction=t,this.render(),this.emit("change",{detail:{value:this._state.selectedValue,index:this._state.selectedIndex,source:t}}))}getValue(){return this._state.selectedValue}onSwatchKeydown=s(e=>{if(this._swatches.length===0||this.disabled)return;let t=this._state.activeIndex??0,r=this._swatches.length-1;if(e.key==="ArrowRight"||e.key==="ArrowDown"){e.preventDefault(),this.selectByIndex(E(t,1,r),"keyboard");return}if(e.key==="ArrowLeft"||e.key==="ArrowUp"){e.preventDefault(),this.selectByIndex(E(t,-1,r),"keyboard");return}(e.key===" "||e.key==="Enter")&&(e.preventDefault(),this.selectByIndex(t,"keyboard"))},"onSwatchKeydown");onSwatchClick=s(e=>{if(this.disabled)return;let t=e.currentTarget,r=Number(t.dataset.index);this.selectByIndex(r,"pointer")},"onSwatchClick");render(){this.setAttribute("role","radiogroup");let e=this.getAttribute("aria-label")??"Color swatches";this.setAttribute("aria-label",e);let t=this._swatches.map((r,i)=>{let o=this._state.selectedIndex===i;return`
|
|
2
|
+
<button
|
|
3
|
+
type="button"
|
|
4
|
+
class="swatch${this._state.activeIndex===i?" is-active":""}"
|
|
5
|
+
role="radio"
|
|
6
|
+
aria-label="${r}"
|
|
7
|
+
aria-checked="${o?"true":"false"}"
|
|
8
|
+
data-index="${i}"
|
|
9
|
+
data-value="${r}"
|
|
10
|
+
style="background:${r};"
|
|
11
|
+
${this.disabled?"disabled":""}
|
|
12
|
+
></button>
|
|
13
|
+
`}).join("");this.innerHTML=`<div class="picker">${t}</div>`,this.querySelectorAll(".swatch").forEach(r=>{r.addEventListener("click",this.onSwatchClick),r.addEventListener("keydown",this.onSwatchKeydown)})}};u(l.TAG,l);function L(n){if(!n||typeof n!="string")return!1;let e=new Option;return e.style.color="",e.style.color=n,e.style.color!==""}s(L,"isValidCssColor");function T(n){return n.filter(L)}s(T,"sanitizeSwatches");function y(n=null,e=null){return{activeIndex:n,selectedIndex:n,selectedValue:e,lastInteraction:null}}s(y,"createSelectionState");function W(n,e){return e<0?-1:n<0?0:n>e?e:n}s(W,"clampIndex");function E(n,e,t){let r=n+e;return r<0?t:r>t?0:r}s(E,"nextIndex");export{l as ColorPicker};
|
|
14
|
+
//# sourceMappingURL=index.min.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../node_modules/@substrate-system/web-component/src/attributes.ts", "../node_modules/@substrate-system/web-component/src/util.ts", "../node_modules/@substrate-system/web-component/src/index.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["export type Attrs = Record<string, undefined|null|string|number|boolean|(string|number)[]>\n\n/**\n * Transform an object into an HTML attributes string. The object should be\n * like `{ attributeName: value }`.\n *\n * @param attrs An object for the attributes.\n * @returns {string} A string suitable for use as HTML attributes.\n */\nexport function toAttributes (attrs:Attrs):string {\n return Object.keys(attrs).reduce((acc, k) => {\n const value = attrs[k]\n if (!value) return acc\n\n if (typeof value === 'boolean') {\n if (value) return (acc + ` ${k}`).trim()\n return acc\n }\n\n if (Array.isArray(value)) {\n return (acc + ` ${k}=\"${value.join(' ')}\"`)\n }\n\n return (acc + ` ${k}=\"${value}\"`).trim()\n }, '')\n}\n", "export { toAttributes } from './attributes.js'\n\n/**\n * Check if the given tag name has been registered.\n *\n * @see {@link https://stackoverflow.com/a/28210364 stackoverflow}\n * @param {string} elName The custom element tag name.\n * @returns {boolean} True if the given name has been registered already.\n */\nexport function isRegistered (elName:string):boolean {\n return document.createElement(elName).constructor !== window.HTMLElement\n}\n\nexport function define (name:string, element:CustomElementConstructor) {\n if (!window) return\n if (!('customElements' in window)) return\n\n if (!isRegistered(name)) {\n window.customElements.define(name, element)\n }\n}\n\nexport const qs = document.querySelector.bind(document)\nexport const qsa = document.querySelectorAll.bind(document)\n\n/**\n * Get the closes parent element matching the given selector.\n * @param el Element to start from\n * @param s Selector for an element\n * @returns {HTMLElement|null} The closes parent element that matches.\n */\nexport function match (el:HTMLElement, s:string):HTMLElement|null {\n if (!el.matches) el = el.parentElement!\n return el.matches(s) ? el : el.closest(s)\n}\n", "import { match as _match } from './util.js'\n\ninterface WildcardListenerEntry {\n listener:EventListenerOrEventListenerObject\n options?:boolean|AddEventListenerOptions\n}\n\nexport abstract class WebComponent extends window.HTMLElement {\n static TAG:string = ''\n TAG:string = ''\n\n static match (el:HTMLElement):HTMLElement|null {\n return _match(el, this.TAG)\n }\n\n /**\n * Store global wildcard listeners (listen to all events)\n * Triggered by ALL events dispatched through this element\n * @private\n */\n private _globalWildcardListeners:Set<WildcardListenerEntry> = new Set()\n\n /**\n * Store namespaced wildcard listeners (listen to 'component-name:*')\n * Triggered by events from emit() that match this component's namespace\n * @private\n */\n private _namespacedWildcardListeners:Set<WildcardListenerEntry> = new Set()\n\n static create (elementName:string):typeof WebComponent & {\n new (...args:any[]):WebComponent;\n TAG:string;\n define: typeof WebComponent.define;\n event: typeof WebComponent.event;\n } {\n const CreatedClass = class extends WebComponent {\n static TAG = elementName\n TAG = elementName\n render () {\n throw new Error('`render` should be implemented by children')\n }\n }\n\n // Copy static methods with proper binding\n CreatedClass.define = function () {\n return WebComponent.define.call(this)\n }\n CreatedClass.event = function (evType:string) {\n return WebComponent.event.call(this, evType)\n }\n\n return CreatedClass\n }\n\n static define<T extends {\n new (...args:any[]):WebComponent;\n TAG:string;\n }>(this:T) {\n define(this.TAG, this)\n }\n\n /**\n * Runs when the value of an attribute is changed.\n *\n * Depends on `static observedAttributes`.\n *\n * Should name methods like `handleChange_disabled`.\n *\n * @param {string} name The attribute name\n * @param {string} oldValue The old attribute value\n * @param {string} newValue The new attribute value\n */\n async attributeChangedCallback (\n name:string,\n oldValue:string,\n newValue:string\n ):Promise<void> {\n const handler = this[`handleChange_${name}`]\n if (handler) {\n await handler.call(this, oldValue, newValue)\n }\n }\n\n /**\n * Enhanced addEventListener that supports wildcards:\n * - Component.event('*') - Listen to all namespaced events for this\n * component (e.g., 'my-component:*')\n * - '*' - Listen to ALL events (namespaced and non-namespaced, including\n * normal DOM events)\n *\n * @param type - Event type, Component.event('*') for namespaced wildcard,\n * or '*' for global wildcard\n * @param listener - Event listener function or object\n * @param options - Event listener options\n */\n addEventListener (\n type:string,\n listener:EventListenerOrEventListenerObject,\n options?:boolean|AddEventListenerOptions\n ): void {\n if (type === WebComponent.event.call(this, '*')) {\n // Handle namespaced wildcard listener (component-name:*)\n this._namespacedWildcardListeners.add({ listener, options })\n } else if (type === '*') {\n // Handle global wildcard listener (all events)\n if (listener) {\n this._globalWildcardListeners.add({ listener, options })\n }\n } else {\n // Normal event listener - delegate to native implementation\n super.addEventListener(type, listener, options)\n }\n }\n\n /**\n * Notify namespaced wildcard listeners of an event\n * Only fires for events that match this component's namespace\n *\n * @param event - The event to dispatch to namespaced wildcard listeners\n * @private\n */\n private _notifyNamespacedWildcardListeners (event: Event): void {\n if (this._namespacedWildcardListeners.size === 0) {\n return\n }\n\n const componentName = this.TAG\n\n // Only trigger for events in this component's namespace\n if (!componentName || !event.type.startsWith(`${componentName}:`)) {\n return\n }\n\n // Call each namespaced wildcard listener\n this._namespacedWildcardListeners.forEach(({ listener }) => {\n try {\n if (typeof listener === 'function') {\n listener.call(this, event)\n } else if (listener && typeof listener.handleEvent === 'function') {\n listener.handleEvent(event)\n }\n } catch (error) {\n // Log errors but don't let one listener break others\n console.error(\n 'Error in namespaced wildcard event listener:',\n error\n )\n }\n })\n }\n\n /**\n * Notify global wildcard listeners of an event\n * Fires for ALL events dispatched through this element\n *\n * @param event - The event to dispatch to global wildcard listeners\n * @private\n */\n private _notifyGlobalWildcardListeners (event: Event): void {\n if (this._globalWildcardListeners.size === 0) {\n return\n }\n\n // Call each global wildcard listener\n this._globalWildcardListeners.forEach(({ listener }) => {\n try {\n if (typeof listener === 'function') {\n listener.call(this, event)\n } else if (listener && typeof listener.handleEvent === 'function') {\n listener.handleEvent(event)\n }\n } catch (error) {\n // Log errors but don't let one listener break others\n console.error('Error in global wildcard event listener:', error)\n }\n })\n }\n\n connectedCallback () {\n this.render()\n }\n\n abstract render ():any\n\n qs<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):HTMLElementTagNameMap[K]|null;\n\n qs<E extends Element = Element>(selector:string):E|null;\n qs (selector:string):Element|null {\n return this.querySelector(selector)\n }\n\n qsa<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):HTMLElementTagNameMap[K]|null;\n\n qsa<E extends Element = Element>(selector:string):E|null;\n qsa (selector:string):NodeListOf<Element> {\n return this.querySelectorAll(selector)\n }\n\n /**\n * Take a non-namepsaced event name, return namespace event name.\n *\n * @param {string} evType The non-namespace event name\n * @returns {string} Namespaced event name, eg, `my-component:click`\n */\n static event (evType:string):string {\n return eventName(this.TAG, evType)\n }\n\n /**\n * Emit a namespaced event.\n *\n * @param type (non-namespaced) event type string\n * @param opts `bubbles`, `detail`, and `cancelable`. Default is\n * `{ bubbles: true, cancelable: true }`\n * @returns {boolean}\n */\n emit<T = any> (type:string, opts:Partial<{\n bubbles:boolean,\n cancelable:boolean,\n detail:CustomEvent<T>['detail']\n }> = {}):boolean {\n if (type === '*') throw new Error('Do not emit the literal \"*\"')\n\n const { bubbles = true, cancelable = true, detail } = opts\n const namespacedType = `${this.TAG}:${type}`\n\n const event = new CustomEvent(namespacedType, {\n bubbles,\n cancelable,\n detail\n })\n\n // This will trigger both specific listeners and global wildcard\n // listeners (**)\n const result = this.dispatchEvent(event)\n\n // Notify namespaced wildcard listeners (*)\n this._notifyNamespacedWildcardListeners(event)\n\n return result\n }\n\n /**\n * Override dispatchEvent to notify global wildcard listeners\n * This ensures that '**' listeners catch ALL events\n *\n * @param event - The event to dispatch\n * @returns true if the event was not cancelled\n */\n dispatchEvent (event: Event): boolean {\n const result = super.dispatchEvent(event)\n\n // Notify global wildcard listeners for ALL events\n this._notifyGlobalWildcardListeners(event)\n\n return result\n }\n\n /**\n * Create and emit an event, no namespacing.\n */\n dispatch<T> (type:string, opts:Partial<{\n bubbles:boolean,\n cancelable:boolean,\n detail:CustomEvent<T>['detail']\n }> = {}):boolean {\n const event = new CustomEvent(type, {\n bubbles: (opts.bubbles === undefined) ? true : opts.bubbles,\n cancelable: (opts.cancelable === undefined) ? true : opts.cancelable,\n detail: opts.detail\n })\n\n return this.dispatchEvent(event)\n }\n\n /**\n * Listen for namespaced events.\n */\n on<T extends Event = Event> (\n evName:string,\n handler:(ev:T)=>any,\n options?:boolean|AddEventListenerOptions\n ):void;\n\n on (\n evName:string,\n handler:EventListenerObject,\n options?:boolean|AddEventListenerOptions\n ):void;\n\n on (\n evName:string,\n handler:((ev:Event)=>any)|EventListenerObject,\n options?:boolean|AddEventListenerOptions\n ):void {\n const fullEvName = WebComponent.event.call(this, evName)\n this.addEventListener(fullEvName, handler as EventListenerOrEventListenerObject, options)\n }\n\n /**\n * Enhanced removeEventListener that supports wildcards:\n * - Component.event('*') - Remove namespaced wildcard listener\n * - '*' - Remove global wildcard listener\n *\n * @param type - Event type, Component.event('*') for namespaced, or '*'\n * for global\n * @param listener - Event listener function or object to remove\n * @param options - Event listener options\n */\n removeEventListener (\n type:string,\n listener:EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions\n ): void {\n if (type === WebComponent.event.call(this, '*')) {\n // Remove namespaced wildcard listener\n if (listener && this._namespacedWildcardListeners) {\n for (const entry of this._namespacedWildcardListeners) {\n if (entry.listener === listener) {\n this._namespacedWildcardListeners.delete(entry)\n break\n }\n }\n }\n } else if (type === '*') {\n // Remove global wildcard listener\n if (listener && this._globalWildcardListeners) {\n for (const entry of this._globalWildcardListeners) {\n if (entry.listener === listener) {\n this._globalWildcardListeners.delete(entry)\n break\n }\n }\n }\n } else {\n // Normal event listener - delegate to native implementation\n super.removeEventListener(type, listener, options)\n }\n }\n}\n\nfunction eventName (namespace:string, evType:string) {\n return `${namespace}:${evType}`\n}\n\n/**\n * Check if the given tag name has been registered.\n *\n * @see {@link https://stackoverflow.com/a/28210364 stackoverflow}\n * @param {string} elName The custom element tag name.\n * @returns {boolean} True if the given name has been registered already.\n */\nexport function isRegistered (elName:string):boolean {\n return document.createElement(elName).constructor !== window.HTMLElement\n}\n\nexport function define (name:string, element:CustomElementConstructor) {\n if (!window) return\n if (!('customElements' in window)) return\n\n if (!isRegistered(name)) {\n window.customElements.define(name, element)\n }\n}\n", "import { WebComponent } from '@substrate-system/web-component'\nimport { define } from '@substrate-system/web-component/util'\nimport './index.css'\n\ntype InteractionSource = 'pointer'|'keyboard'|'programmatic'\n\nexport interface ChangeDetail {\n value:string|null\n index:number|null\n source:InteractionSource\n}\n\nexport type ChangeEvent = CustomEvent<ChangeDetail>\n\ninterface SelectionState {\n activeIndex:number|null\n selectedIndex:number|null\n selectedValue:string|null\n lastInteraction:InteractionSource|null\n}\n\nconst DEFAULT_SWATCHES = [\n '#000000',\n '#f8fafc',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#22c55e',\n '#3b82f6',\n '#8b5cf6',\n '#ec4899'\n]\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'color-picker':ColorPicker\n }\n}\n\nexport class ColorPicker extends WebComponent.create('color-picker') {\n static observedAttributes = ['value', 'disabled', 'aria-label']\n\n private _swatches:string[] = [...DEFAULT_SWATCHES]\n private _state = createSelectionState(0, DEFAULT_SWATCHES[0])\n\n get swatches ():string[] {\n return [...this._swatches]\n }\n\n set swatches (values:string[]) {\n const sanitized = sanitizeSwatches(values)\n if (sanitized.length !== values.length) {\n console.warn('color-picker: invalid CSS color values were ignored')\n }\n\n this._swatches = sanitized\n\n if (this._swatches.length === 0) {\n this._state = createSelectionState()\n this.render()\n return\n }\n\n if (\n this._state.selectedIndex == null ||\n this._state.selectedIndex >= this._swatches.length ||\n this._state.selectedValue !== this._swatches[this._state.selectedIndex]\n ) {\n this.selectByIndex(0, 'programmatic')\n return\n }\n\n this.render()\n }\n\n get value ():string|null {\n return this._state.selectedValue\n }\n\n set value (nextValue:string|null) {\n if (nextValue == null) {\n this._state.selectedIndex = null\n this._state.selectedValue = null\n this._state.activeIndex = null\n this.render()\n return\n }\n\n const idx = this._swatches.findIndex((entry) => entry === nextValue)\n if (idx === -1) return\n this.selectByIndex(idx, 'programmatic')\n }\n\n get disabled ():boolean {\n return this.hasAttribute('disabled')\n }\n\n set disabled (isDisabled:boolean) {\n if (isDisabled) {\n this.setAttribute('disabled', '')\n } else {\n this.removeAttribute('disabled')\n }\n this.render()\n }\n\n connectedCallback ():void {\n super.connectedCallback()\n this.setAttribute('role', 'radiogroup')\n this.render()\n }\n\n handleChange_value (_oldValue:string, newValue:string):void {\n if (!newValue || !isValidCssColor(newValue)) return\n this.value = newValue\n }\n\n setSwatches (swatches:string[]):void {\n this.swatches = swatches\n }\n\n selectByIndex (index:number, source:InteractionSource = 'programmatic'):void {\n if (this._swatches.length === 0) return\n const max = this._swatches.length - 1\n const normalized = clampIndex(index, max)\n if (normalized < 0 || normalized > max) return\n\n this._state.selectedIndex = normalized\n this._state.activeIndex = normalized\n this._state.selectedValue = this._swatches[normalized]\n this._state.lastInteraction = source\n this.render()\n\n this.emit<ChangeDetail>('change', {\n detail: {\n value: this._state.selectedValue,\n index: this._state.selectedIndex,\n source\n }\n })\n }\n\n getValue ():string|null {\n return this._state.selectedValue\n }\n\n private onSwatchKeydown = (ev:KeyboardEvent):void => {\n if (this._swatches.length === 0 || this.disabled) return\n const current = this._state.activeIndex ?? 0\n const max = this._swatches.length - 1\n\n if (ev.key === 'ArrowRight' || ev.key === 'ArrowDown') {\n ev.preventDefault()\n this.selectByIndex(nextIndex(current, 1, max), 'keyboard')\n return\n }\n\n if (ev.key === 'ArrowLeft' || ev.key === 'ArrowUp') {\n ev.preventDefault()\n this.selectByIndex(nextIndex(current, -1, max), 'keyboard')\n return\n }\n\n if (ev.key === ' ' || ev.key === 'Enter') {\n ev.preventDefault()\n this.selectByIndex(current, 'keyboard')\n }\n }\n\n private onSwatchClick = (ev:Event):void => {\n if (this.disabled) return\n const target = ev.currentTarget as HTMLElement\n const idx = Number(target.dataset.index)\n this.selectByIndex(idx, 'pointer')\n }\n\n render ():void {\n this.setAttribute('role', 'radiogroup')\n\n const label = this.getAttribute('aria-label') ?? 'Color swatches'\n this.setAttribute('aria-label', label)\n\n const swatchesHtml = this._swatches.map((value, index) => {\n const checked = this._state.selectedIndex === index\n const active = this._state.activeIndex === index\n\n return `\n <button\n type=\"button\"\n class=\"swatch${active ? ' is-active' : ''}\"\n role=\"radio\"\n aria-label=\"${value}\"\n aria-checked=\"${checked ? 'true' : 'false'}\"\n data-index=\"${index}\"\n data-value=\"${value}\"\n style=\"background:${value};\"\n ${this.disabled ? 'disabled' : ''}\n ></button>\n `\n }).join('')\n\n this.innerHTML = `<div class=\"picker\">${swatchesHtml}</div>`\n\n this.querySelectorAll<HTMLButtonElement>('.swatch').forEach((swatch) => {\n swatch.addEventListener('click', this.onSwatchClick)\n swatch.addEventListener('keydown', this.onSwatchKeydown)\n })\n }\n}\n\ndefine(ColorPicker.TAG, ColorPicker)\n\nfunction isValidCssColor (value:string):boolean {\n if (!value || typeof value !== 'string') return false\n const option = new Option()\n option.style.color = ''\n option.style.color = value\n return option.style.color !== ''\n}\n\nfunction sanitizeSwatches (swatches:string[]):string[] {\n return swatches.filter(isValidCssColor)\n}\n\nfunction createSelectionState (selectedIndex:number|null = null, selectedValue:string|null = null):SelectionState {\n return {\n activeIndex: selectedIndex,\n selectedIndex,\n selectedValue,\n lastInteraction: null\n }\n}\n\nfunction clampIndex (index:number, max:number):number {\n if (max < 0) return -1\n if (index < 0) return 0\n if (index > max) return max\n return index\n}\n\nfunction nextIndex (current:number, delta:number, max:number):number {\n const raw = current + delta\n if (raw < 0) return max\n if (raw > max) return 0\n return raw\n}\n"],
|
|
5
|
+
"mappings": "sKASO,SAASA,EAAcC,EAAoB,CAC9C,OAAO,OAAO,KAAKA,CAAK,EAAE,OAAO,CAACC,EAAKC,IAAM,CACzC,IAAMC,EAAQH,EAAME,CAAC,EACrB,OAAKC,EAED,OAAOA,GAAU,UACbA,GAAeF,EAAM,IAAIC,CAAC,IAAI,KAAK,EAChCD,EAGP,MAAM,QAAQE,CAAK,EACXF,EAAM,IAAIC,CAAC,KAAKC,EAAM,KAAK,GAAG,CAAC,KAGnCF,EAAM,IAAIC,CAAC,KAAKC,CAAK,KAAK,KAAK,EAXpBF,CAYvB,EAAG,EAAE,CACT,CAhBgBG,EAAAL,EAAA,gBAAAK,EAAAL,EAAA,cAAA,yFCAT,SAASM,EAAcC,EAAuB,CACjD,OAAO,SAAS,cAAcA,CAAM,EAAE,cAAgB,OAAO,WACjE,CAFgBC,EAAAF,EAAA,gBAAAE,EAAAF,EAAA,cAAA,EAIT,SAASG,EAAQC,EAAaC,EAAkC,CAC9D,QACC,mBAAoB,SAErBL,EAAaI,CAAI,GAClB,OAAO,eAAe,OAAOA,EAAMC,CAAO,EAElD,CAPgBH,EAAAC,EAAA,UAAAD,EAAAC,EAAA,QAAA,EAST,IAAMG,EAAK,SAAS,cAAc,KAAK,QAAQ,EACzCC,EAAM,SAAS,iBAAiB,KAAK,QAAQ,EAQnD,SAASC,EAAOC,EAAgBC,EAA2B,CAC9D,OAAKD,EAAG,UAASA,EAAKA,EAAG,eAClBA,EAAG,QAAQC,CAAC,EAAID,EAAKA,EAAG,QAAQC,CAAC,CAC5C,CAHgBR,EAAAM,EAAA,SAAAN,EAAAM,EAAA,OAAA,yFCxBMG,EAAf,MAAeC,UAAqB,OAAO,WAAY,OAAA,CAAAC,EAAA,qBAP9D,MAO8D,CAAAA,EAAA,KAAA,cAAA,CAAA,CAC1D,OAAO,IAAa,GACpB,IAAa,GAEb,OAAO,MAAOC,EAAiC,CAC3C,OAAOC,EAAOD,EAAI,KAAK,GAAG,CAC9B,CAOQ,yBAAsD,IAAI,IAO1D,6BAA0D,IAAI,IAEtE,OAAO,OAAQE,EAKb,CACE,IAAMC,EAAe,cAAcL,CAAa,OAAA,CAAAC,EAAA,qBAnCxD,MAmCwD,CAAAA,EAAA,KAAA,cAAA,CAAA,CAC5C,OAAO,IAAMG,EACb,IAAMA,EACN,QAAU,CACN,MAAM,IAAI,MAAM,4CAA4C,CAChE,CACJ,EAGA,OAAAC,EAAa,OAAS,UAAY,CAC9B,OAAOL,EAAa,OAAO,KAAK,IAAI,CACxC,EACAK,EAAa,MAAQ,SAAUC,EAAe,CAC1C,OAAON,EAAa,MAAM,KAAK,KAAMM,CAAM,CAC/C,EAEOD,CACX,CAEA,OAAO,QAGI,CACPE,EAAO,KAAK,IAAK,IAAI,CACzB,CAaA,MAAM,yBACFC,EACAC,EACAC,EACY,CACZ,IAAMC,EAAU,KAAK,gBAAgBH,CAAI,EAAE,EACvCG,GACA,MAAMA,EAAQ,KAAK,KAAMF,EAAUC,CAAQ,CAEnD,CAcA,iBACIE,EACAC,EACAC,EACI,CACAF,IAASZ,EAAa,MAAM,KAAK,KAAM,GAAG,EAE1C,KAAK,6BAA6B,IAAI,CAAE,SAAAa,EAAU,QAAAC,CAAQ,CAAC,EACpDF,IAAS,IAEZC,GACA,KAAK,yBAAyB,IAAI,CAAE,SAAAA,EAAU,QAAAC,CAAQ,CAAC,EAI3D,MAAM,iBAAiBF,EAAMC,EAAUC,CAAO,CAEtD,CASQ,mCAAoCC,EAAoB,CAC5D,GAAI,KAAK,6BAA6B,OAAS,EAC3C,OAGJ,IAAMC,EAAgB,KAAK,IAGvB,CAACA,GAAiB,CAACD,EAAM,KAAK,WAAW,GAAGC,CAAa,GAAG,GAKhE,KAAK,6BAA6B,QAAQ,CAAC,CAAE,SAAAH,CAAS,IAAM,CACxD,GAAI,CACI,OAAOA,GAAa,WACpBA,EAAS,KAAK,KAAME,CAAK,EAClBF,GAAY,OAAOA,EAAS,aAAgB,YACnDA,EAAS,YAAYE,CAAK,CAElC,OAASE,EAAO,CAEZ,QAAQ,MACJ,+CACAA,CACJ,CACJ,CACJ,CAAC,CACL,CASQ,+BAAgCF,EAAoB,CACpD,KAAK,yBAAyB,OAAS,GAK3C,KAAK,yBAAyB,QAAQ,CAAC,CAAE,SAAAF,CAAS,IAAM,CACpD,GAAI,CACI,OAAOA,GAAa,WACpBA,EAAS,KAAK,KAAME,CAAK,EAClBF,GAAY,OAAOA,EAAS,aAAgB,YACnDA,EAAS,YAAYE,CAAK,CAElC,OAASE,EAAO,CAEZ,QAAQ,MAAM,2CAA4CA,CAAK,CACnE,CACJ,CAAC,CACL,CAEA,mBAAqB,CACjB,KAAK,OAAO,CAChB,CASA,GAAIC,EAA8B,CAC9B,OAAO,KAAK,cAAcA,CAAQ,CACtC,CAOA,IAAKA,EAAqC,CACtC,OAAO,KAAK,iBAAiBA,CAAQ,CACzC,CAQA,OAAO,MAAOZ,EAAsB,CAChC,OAAOa,EAAU,KAAK,IAAKb,CAAM,CACrC,CAUA,KAAeM,EAAaQ,EAIvB,CAAC,EAAW,CACb,GAAIR,IAAS,IAAK,MAAM,IAAI,MAAM,6BAA6B,EAE/D,GAAM,CAAE,QAAAS,EAAU,GAAM,WAAAC,EAAa,GAAM,OAAAC,CAAO,EAAIH,EAChDI,EAAiB,GAAG,KAAK,GAAG,IAAIZ,CAAI,GAEpCG,EAAQ,IAAI,YAAYS,EAAgB,CAC1C,QAAAH,EACA,WAAAC,EACA,OAAAC,CACJ,CAAC,EAIKE,EAAS,KAAK,cAAcV,CAAK,EAGvC,YAAK,mCAAmCA,CAAK,EAEtCU,CACX,CASA,cAAeV,EAAuB,CAClC,IAAMU,EAAS,MAAM,cAAcV,CAAK,EAGxC,YAAK,+BAA+BA,CAAK,EAElCU,CACX,CAKA,SAAab,EAAaQ,EAIrB,CAAC,EAAW,CACb,IAAML,EAAQ,IAAI,YAAYH,EAAM,CAChC,QAAUQ,EAAK,UAAY,OAAa,GAAOA,EAAK,QACpD,WAAaA,EAAK,aAAe,OAAa,GAAOA,EAAK,WAC1D,OAAQA,EAAK,MACjB,CAAC,EAED,OAAO,KAAK,cAAcL,CAAK,CACnC,CAiBA,GACIW,EACAf,EACAG,EACG,CACH,IAAMa,EAAa3B,EAAa,MAAM,KAAK,KAAM0B,CAAM,EACvD,KAAK,iBAAiBC,EAAYhB,EAA+CG,CAAO,CAC5F,CAYA,oBACIF,EACAC,EACAC,EACI,CACJ,GAAIF,IAASZ,EAAa,MAAM,KAAK,KAAM,GAAG,GAE1C,GAAIa,GAAY,KAAK,8BACjB,QAAWe,KAAS,KAAK,6BACrB,GAAIA,EAAM,WAAaf,EAAU,CAC7B,KAAK,6BAA6B,OAAOe,CAAK,EAC9C,KACJ,WAGDhB,IAAS,KAEhB,GAAIC,GAAY,KAAK,0BACjB,QAAWe,KAAS,KAAK,yBACrB,GAAIA,EAAM,WAAaf,EAAU,CAC7B,KAAK,yBAAyB,OAAOe,CAAK,EAC1C,KACJ,QAKR,MAAM,oBAAoBhB,EAAMC,EAAUC,CAAO,CAEzD,CACJ,EAEA,SAASK,EAAWU,EAAkBvB,EAAe,CACjD,MAAO,GAAGuB,CAAS,IAAIvB,CAAM,EACjC,CAFSL,EAAAkB,EAAA,aAAAlB,EAAAkB,EAAA,WAAA,EAWF,SAASW,EAAcC,EAAuB,CACjD,OAAO,SAAS,cAAcA,CAAM,EAAE,cAAgB,OAAO,WACjE,CAFgB9B,EAAA6B,EAAA,gBAAA7B,EAAA6B,EAAA,cAAA,EAIT,SAASvB,EAAQC,EAAawB,EAAkC,CAC9D,QACC,mBAAoB,SAErBF,EAAatB,CAAI,GAClB,OAAO,eAAe,OAAOA,EAAMwB,CAAO,EAElD,CAPgB/B,EAAAM,EAAA,UAAAN,EAAAM,EAAA,QAAA,ECnVhB,IAAM0B,EAAmB,CACrB,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,SACJ,EASaC,EAAN,cAA0BC,EAAa,OAAO,cAAc,CAAE,CAxCrE,MAwCqE,CAAAC,EAAA,oBACjE,OAAO,mBAAqB,CAAC,QAAS,WAAY,YAAY,EAEtD,UAAqB,CAAC,GAAGH,CAAgB,EACzC,OAASI,EAAqB,EAAGJ,EAAiB,CAAC,CAAC,EAE5D,IAAI,UAAqB,CACrB,MAAO,CAAC,GAAG,KAAK,SAAS,CAC7B,CAEA,IAAI,SAAUK,EAAiB,CAC3B,IAAMC,EAAYC,EAAiBF,CAAM,EAOzC,GANIC,EAAU,SAAWD,EAAO,QAC5B,QAAQ,KAAK,qDAAqD,EAGtE,KAAK,UAAYC,EAEb,KAAK,UAAU,SAAW,EAAG,CAC7B,KAAK,OAASF,EAAqB,EACnC,KAAK,OAAO,EACZ,MACJ,CAEA,GACI,KAAK,OAAO,eAAiB,MAC7B,KAAK,OAAO,eAAiB,KAAK,UAAU,QAC5C,KAAK,OAAO,gBAAkB,KAAK,UAAU,KAAK,OAAO,aAAa,EACxE,CACE,KAAK,cAAc,EAAG,cAAc,EACpC,MACJ,CAEA,KAAK,OAAO,CAChB,CAEA,IAAI,OAAqB,CACrB,OAAO,KAAK,OAAO,aACvB,CAEA,IAAI,MAAOI,EAAuB,CAC9B,GAAIA,GAAa,KAAM,CACnB,KAAK,OAAO,cAAgB,KAC5B,KAAK,OAAO,cAAgB,KAC5B,KAAK,OAAO,YAAc,KAC1B,KAAK,OAAO,EACZ,MACJ,CAEA,IAAMC,EAAM,KAAK,UAAU,UAAWC,GAAUA,IAAUF,CAAS,EAC/DC,IAAQ,IACZ,KAAK,cAAcA,EAAK,cAAc,CAC1C,CAEA,IAAI,UAAoB,CACpB,OAAO,KAAK,aAAa,UAAU,CACvC,CAEA,IAAI,SAAUE,EAAoB,CAC1BA,EACA,KAAK,aAAa,WAAY,EAAE,EAEhC,KAAK,gBAAgB,UAAU,EAEnC,KAAK,OAAO,CAChB,CAEA,mBAA0B,CACtB,MAAM,kBAAkB,EACxB,KAAK,aAAa,OAAQ,YAAY,EACtC,KAAK,OAAO,CAChB,CAEA,mBAAoBC,EAAkBC,EAAsB,CACpD,CAACA,GAAY,CAACC,EAAgBD,CAAQ,IAC1C,KAAK,MAAQA,EACjB,CAEA,YAAaE,EAAwB,CACjC,KAAK,SAAWA,CACpB,CAEA,cAAeC,EAAcC,EAA2B,eAAqB,CACzE,GAAI,KAAK,UAAU,SAAW,EAAG,OACjC,IAAMC,EAAM,KAAK,UAAU,OAAS,EAC9BC,EAAaC,EAAWJ,EAAOE,CAAG,EACpCC,EAAa,GAAKA,EAAaD,IAEnC,KAAK,OAAO,cAAgBC,EAC5B,KAAK,OAAO,YAAcA,EAC1B,KAAK,OAAO,cAAgB,KAAK,UAAUA,CAAU,EACrD,KAAK,OAAO,gBAAkBF,EAC9B,KAAK,OAAO,EAEZ,KAAK,KAAmB,SAAU,CAC9B,OAAQ,CACJ,MAAO,KAAK,OAAO,cACnB,MAAO,KAAK,OAAO,cACnB,OAAAA,CACJ,CACJ,CAAC,EACL,CAEA,UAAwB,CACpB,OAAO,KAAK,OAAO,aACvB,CAEQ,gBAAkBd,EAACkB,GAA0B,CACjD,GAAI,KAAK,UAAU,SAAW,GAAK,KAAK,SAAU,OAClD,IAAMC,EAAU,KAAK,OAAO,aAAe,EACrCJ,EAAM,KAAK,UAAU,OAAS,EAEpC,GAAIG,EAAG,MAAQ,cAAgBA,EAAG,MAAQ,YAAa,CACnDA,EAAG,eAAe,EAClB,KAAK,cAAcE,EAAUD,EAAS,EAAGJ,CAAG,EAAG,UAAU,EACzD,MACJ,CAEA,GAAIG,EAAG,MAAQ,aAAeA,EAAG,MAAQ,UAAW,CAChDA,EAAG,eAAe,EAClB,KAAK,cAAcE,EAAUD,EAAS,GAAIJ,CAAG,EAAG,UAAU,EAC1D,MACJ,EAEIG,EAAG,MAAQ,KAAOA,EAAG,MAAQ,WAC7BA,EAAG,eAAe,EAClB,KAAK,cAAcC,EAAS,UAAU,EAE9C,EArB0B,mBAuBlB,cAAgBnB,EAACkB,GAAkB,CACvC,GAAI,KAAK,SAAU,OACnB,IAAMG,EAASH,EAAG,cACZZ,EAAM,OAAOe,EAAO,QAAQ,KAAK,EACvC,KAAK,cAAcf,EAAK,SAAS,CACrC,EALwB,iBAOxB,QAAe,CACX,KAAK,aAAa,OAAQ,YAAY,EAEtC,IAAMgB,EAAQ,KAAK,aAAa,YAAY,GAAK,iBACjD,KAAK,aAAa,aAAcA,CAAK,EAErC,IAAMC,EAAe,KAAK,UAAU,IAAI,CAACC,EAAOX,IAAU,CACtD,IAAMY,EAAU,KAAK,OAAO,gBAAkBZ,EAG9C,MAAO;AAAA;AAAA;AAAA,yBAFQ,KAAK,OAAO,cAAgBA,EAKrB,aAAe,EAAE;AAAA;AAAA,wBAE3BW,CAAK;AAAA,0BACHC,EAAU,OAAS,OAAO;AAAA,wBAC5BZ,CAAK;AAAA,wBACLW,CAAK;AAAA,8BACCA,CAAK;AAAA,YACvB,KAAK,SAAW,WAAa,EAAE;AAAA;AAAA,OAGnC,CAAC,EAAE,KAAK,EAAE,EAEV,KAAK,UAAY,uBAAuBD,CAAY,SAEpD,KAAK,iBAAoC,SAAS,EAAE,QAASG,GAAW,CACpEA,EAAO,iBAAiB,QAAS,KAAK,aAAa,EACnDA,EAAO,iBAAiB,UAAW,KAAK,eAAe,CAC3D,CAAC,CACL,CACJ,EAEAC,EAAO7B,EAAY,IAAKA,CAAW,EAEnC,SAASa,EAAiBa,EAAsB,CAC5C,GAAI,CAACA,GAAS,OAAOA,GAAU,SAAU,MAAO,GAChD,IAAMI,EAAS,IAAI,OACnB,OAAAA,EAAO,MAAM,MAAQ,GACrBA,EAAO,MAAM,MAAQJ,EACdI,EAAO,MAAM,QAAU,EAClC,CANS5B,EAAAW,EAAA,mBAQT,SAASP,EAAkBQ,EAA4B,CACnD,OAAOA,EAAS,OAAOD,CAAe,CAC1C,CAFSX,EAAAI,EAAA,oBAIT,SAASH,EAAsB4B,EAA4B,KAAMC,EAA4B,KAAqB,CAC9G,MAAO,CACH,YAAaD,EACb,cAAAA,EACA,cAAAC,EACA,gBAAiB,IACrB,CACJ,CAPS9B,EAAAC,EAAA,wBAST,SAASgB,EAAYJ,EAAcE,EAAmB,CAClD,OAAIA,EAAM,EAAU,GAChBF,EAAQ,EAAU,EAClBA,EAAQE,EAAYA,EACjBF,CACX,CALSb,EAAAiB,EAAA,cAOT,SAASG,EAAWD,EAAgBY,EAAchB,EAAmB,CACjE,IAAMiB,EAAMb,EAAUY,EACtB,OAAIC,EAAM,EAAUjB,EAChBiB,EAAMjB,EAAY,EACfiB,CACX,CALShC,EAAAoB,EAAA",
|
|
6
|
+
"names": ["toAttributes", "attrs", "acc", "k", "value", "__name", "isRegistered", "elName", "__name", "define", "name", "element", "qs", "qsa", "match", "el", "s", "WebComponent", "_WebComponent", "__name", "el", "match", "elementName", "CreatedClass", "evType", "define", "name", "oldValue", "newValue", "handler", "type", "listener", "options", "event", "componentName", "error", "selector", "eventName", "opts", "bubbles", "cancelable", "detail", "namespacedType", "result", "evName", "fullEvName", "entry", "namespace", "isRegistered", "elName", "element", "DEFAULT_SWATCHES", "ColorPicker", "WebComponent", "__name", "createSelectionState", "values", "sanitized", "sanitizeSwatches", "nextValue", "idx", "entry", "isDisabled", "_oldValue", "newValue", "isValidCssColor", "swatches", "index", "source", "max", "normalized", "clampIndex", "ev", "current", "nextIndex", "target", "label", "swatchesHtml", "value", "checked", "swatch", "define", "option", "selectedIndex", "selectedValue", "delta", "raw"]
|
|
7
|
+
}
|
package/dist/meta.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputs": {
|
|
3
|
+
"src/index.ts": {
|
|
4
|
+
"bytes": 6990,
|
|
5
|
+
"imports": [],
|
|
6
|
+
"format": "esm"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"outputs": {
|
|
10
|
+
"dist/index.js.map": {
|
|
11
|
+
"imports": [],
|
|
12
|
+
"exports": [],
|
|
13
|
+
"inputs": {},
|
|
14
|
+
"bytes": 11243
|
|
15
|
+
},
|
|
16
|
+
"dist/index.js": {
|
|
17
|
+
"imports": [
|
|
18
|
+
{
|
|
19
|
+
"path": "@substrate-system/web-component",
|
|
20
|
+
"kind": "import-statement",
|
|
21
|
+
"external": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "@substrate-system/web-component/util",
|
|
25
|
+
"kind": "import-statement",
|
|
26
|
+
"external": true
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "./index.css",
|
|
30
|
+
"kind": "import-statement",
|
|
31
|
+
"external": true
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"exports": [
|
|
35
|
+
"ColorPicker"
|
|
36
|
+
],
|
|
37
|
+
"entryPoint": "src/index.ts",
|
|
38
|
+
"inputs": {
|
|
39
|
+
"src/index.ts": {
|
|
40
|
+
"bytesInOutput": 5858
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"bytes": 6047
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
color-picker {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
color-picker .picker {
|
|
6
|
+
align-items: center;
|
|
7
|
+
gap: 8px;
|
|
8
|
+
display: flex;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
color-picker .swatch {
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
border: 2px solid #444;
|
|
14
|
+
border-radius: 999px;
|
|
15
|
+
width: 24px;
|
|
16
|
+
height: 24px;
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
color-picker .swatch[aria-checked="true"] {
|
|
21
|
+
box-shadow: inset 0 0 0 2px #fff;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*# sourceMappingURL=./dist/style.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"AAAA;;;;AAGE;;;;;;AAMA;;;;;;;;;AASA","sources":["src/index.css"],"sourcesContent":["color-picker {\n display: inline-block;\n\n & .picker {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n & .swatch {\n width: 24px;\n height: 24px;\n border: 2px solid #444;\n border-radius: 999px;\n cursor: pointer;\n padding: 0;\n }\n\n & .swatch[aria-checked='true'] {\n box-shadow: 0 0 0 2px #fff inset;\n }\n}\n"],"names":[]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
color-picker{display:inline-block}color-picker .picker{align-items:center;gap:8px;display:flex}color-picker .swatch{cursor:pointer;border:2px solid #444;border-radius:999px;width:24px;height:24px;padding:0}color-picker .swatch[aria-checked=true]{box-shadow:inset 0 0 0 2px #fff}
|
|
2
|
+
/*# sourceMappingURL=./dist/style.min.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"AAAA,kCAGE,6DAMA,+GASA","sources":["src/index.css"],"sourcesContent":["color-picker {\n display: inline-block;\n\n & .picker {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n & .swatch {\n width: 24px;\n height: 24px;\n border: 2px solid #444;\n border-radius: 999px;\n cursor: pointer;\n padding: 0;\n }\n\n & .swatch[aria-checked='true'] {\n box-shadow: 0 0 0 2px #fff inset;\n }\n}\n"],"names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@substrate-system/color-picker",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Color picker web component",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"./dist/*"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./dist/index.js",
|
|
12
|
+
"./css": "./dist/index.css",
|
|
13
|
+
"./min/css": "./dist/index.min.css",
|
|
14
|
+
"./min/*": "./dist/*.min.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"lint": "eslint \"./**/*.{ts,js}\"",
|
|
18
|
+
"test": "npm run test:node && npm run test:browser",
|
|
19
|
+
"test:node": "rm -rf .tmp-test && esbuild ./test/build-artifacts.test.ts ./test/example-smoke.test.ts ./test/example-interaction.test.ts --bundle --format=esm --platform=node --outdir=.tmp-test && node --test .tmp-test/*.js",
|
|
20
|
+
"test:browser": "esbuild --bundle --loader:.css=text ./test/index.ts | tapout",
|
|
21
|
+
"build-css": "lightningcss --targets \">= 0.25%\" --sourcemap --nesting src/index.css -o ./dist/style.css",
|
|
22
|
+
"build-css:min": "lightningcss --targets \">= 0.25%\" --sourcemap --minify --nesting src/index.css -o ./dist/style.min.css",
|
|
23
|
+
"build-esm": "esbuild src/index.ts --format=esm --metafile=dist/meta.json --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --sourcemap && tsc --emitDeclarationOnly --project tsconfig.build.json --outDir dist",
|
|
24
|
+
"build-esm:min": "esbuild ./src/index.ts --format=esm --keep-names --bundle --loader:.css=text --tsconfig=tsconfig.build.json --minify --out-extension:.js=.min.js --outdir=./dist --sourcemap",
|
|
25
|
+
"build-example": "mkdir -p ./public && rm -rf ./public/* && NODE_ENV=development vite --mode staging --base=\"/color-picker\" build",
|
|
26
|
+
"build-docs": "typedoc --tsconfig tsconfig.build.json ./src/index.ts",
|
|
27
|
+
"build": "mkdir -p ./dist && rm -rf ./dist/* && npm run build-esm && npm run build-esm:min && npm run build-css && npm run build-css:min",
|
|
28
|
+
"start": "vite",
|
|
29
|
+
"toc": "markdown-toc --maxdepth 3 -i README.md",
|
|
30
|
+
"preversion": "npm run lint && stylelint src/*.css",
|
|
31
|
+
"version": "npm run toc && auto-changelog -p --template keepachangelog --breaking-pattern 'BREAKING CHANGE:' && git add CHANGELOG.md README.md",
|
|
32
|
+
"postversion": "git push --follow-tags && npm publish",
|
|
33
|
+
"prepublishOnly": "npm run build"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@substrate-system/web-component": "^0.0.46"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@substrate-system/css-normalize": "^0.0.13",
|
|
40
|
+
"@substrate-system/debug": "^0.9.60",
|
|
41
|
+
"@substrate-system/dom": "^0.1.13",
|
|
42
|
+
"@substrate-system/tapout": "^0.0.37",
|
|
43
|
+
"@substrate-system/tapzero": "^0.10.16",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
45
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
46
|
+
"browserslist": "^4.28.1",
|
|
47
|
+
"esbuild": "^0.27.0",
|
|
48
|
+
"eslint": "^8.57.0",
|
|
49
|
+
"eslint-config-standard": "^17.1.0",
|
|
50
|
+
"lightningcss": "^1.31.1",
|
|
51
|
+
"lightningcss-cli": "^1.31.1",
|
|
52
|
+
"markdown-toc": "^1.2.0",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vite": "^7.3.1"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [
|
|
57
|
+
"color",
|
|
58
|
+
"picker",
|
|
59
|
+
"web",
|
|
60
|
+
"component"
|
|
61
|
+
],
|
|
62
|
+
"homepage": "https://github.com/substrate-system/color-picker",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/substrate-system/color-picker/issues"
|
|
65
|
+
},
|
|
66
|
+
"repository": {
|
|
67
|
+
"type": "git",
|
|
68
|
+
"url": "git+https://github.com/substrate-system/color-picker.git"
|
|
69
|
+
},
|
|
70
|
+
"author": "nichoth <nichoth@nichoth.com> (https://nichoth.com)",
|
|
71
|
+
"license": "SEE LICENSE IN LICENSE"
|
|
72
|
+
}
|