@vuelor/picker 0.1.0-alpha.3 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/package.json +5 -1
  2. package/env.d.ts +0 -1
  3. package/eslint.config.ts +0 -22
  4. package/index.html +0 -13
  5. package/shims-vue.d.ts +0 -5
  6. package/src/components/ColorPickerCanvas.vue +0 -84
  7. package/src/components/ColorPickerEyeDropper.vue +0 -45
  8. package/src/components/ColorPickerInputHSB.vue +0 -106
  9. package/src/components/ColorPickerInputHSL.vue +0 -109
  10. package/src/components/ColorPickerInputHex.vue +0 -73
  11. package/src/components/ColorPickerInputRGB.vue +0 -104
  12. package/src/components/ColorPickerRoot.vue +0 -110
  13. package/src/components/ColorPickerSliderAlpha.vue +0 -58
  14. package/src/components/ColorPickerSliderBlue.vue +0 -62
  15. package/src/components/ColorPickerSliderGreen.vue +0 -62
  16. package/src/components/ColorPickerSliderHue.vue +0 -61
  17. package/src/components/ColorPickerSliderLightness.vue +0 -62
  18. package/src/components/ColorPickerSliderRed.vue +0 -62
  19. package/src/components/ColorPickerSliderSaturation.vue +0 -63
  20. package/src/composables/useColor.ts +0 -247
  21. package/src/composables/useThumb.ts +0 -131
  22. package/src/index.ts +0 -16
  23. package/src/style/index.css +0 -162
  24. package/src/theme/index.ts +0 -7
  25. package/src/theme/tailwindcss.ts +0 -25
  26. package/src/theme/vanillacss.ts +0 -25
  27. package/src/utils/canvas.ts +0 -59
  28. package/src/utils/color.ts +0 -114
  29. package/src/utils/helpers.ts +0 -13
  30. package/src/utils/parsers.ts +0 -144
  31. package/src/utils/styles.ts +0 -47
  32. package/src/utils/types.ts +0 -19
  33. package/tsconfig.app.json +0 -12
  34. package/tsconfig.json +0 -11
  35. package/tsconfig.node.json +0 -19
  36. package/vite.config.ts +0 -37
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuelor/picker",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "A powerful and customizable color picker component for Vue 3 and Nuxt.js, built with Reka UI and Tailwind CSS.",
@@ -9,6 +9,10 @@
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/olekspolk/vuelor.git"
11
11
  },
12
+ "files": [
13
+ "README.md",
14
+ "dist"
15
+ ],
12
16
  "module": "./dist/index.js",
13
17
  "exports": {
14
18
  ".": {
package/env.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
package/eslint.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import { globalIgnores } from 'eslint/config'
2
- import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
3
- import pluginVue from 'eslint-plugin-vue'
4
- import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
5
-
6
- // To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
7
- // import { configureVueProject } from '@vue/eslint-config-typescript'
8
- // configureVueProject({ scriptLangs: ['ts', 'tsx'] })
9
- // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
10
-
11
- export default defineConfigWithVueTs(
12
- {
13
- name: 'app/files-to-lint',
14
- files: ['**/*.{ts,mts,tsx,vue}'],
15
- },
16
-
17
- globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
18
-
19
- pluginVue.configs['flat/essential'],
20
- vueTsConfigs.recommended,
21
- skipFormatting,
22
- )
package/index.html DELETED
@@ -1,13 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="">
3
- <head>
4
- <meta charset="UTF-8">
5
- <link rel="icon" href="/favicon.ico">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Vite App</title>
8
- </head>
9
- <body>
10
- <div id="app"></div>
11
- <script type="module" src="/src/main.ts"></script>
12
- </body>
13
- </html>
package/shims-vue.d.ts DELETED
@@ -1,5 +0,0 @@
1
- declare module '*.vue' {
2
- import { DefineComponent } from 'vue';
3
- const component: DefineComponent<{}, {}, any>;
4
- export default component;
5
- }
@@ -1,84 +0,0 @@
1
- <script setup lang="ts">
2
- import type { CSSProperties } from 'vue'
3
- import { computed, useTemplateRef, watchEffect } from 'vue'
4
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
5
- import { drawHsvGradient, drawHslGradient } from '../utils/canvas.ts'
6
- import { useThumb } from '../composables/useThumb.ts'
7
-
8
- const rootContext = injectColorPickerContext()
9
- const canvasRef = useTemplateRef<HTMLCanvasElement | null>('canvasRef')
10
-
11
- interface CanvasProps {
12
- type?: 'HSV' | 'HSL',
13
- height?: number,
14
- width?: number,
15
- class?: string,
16
- ui?: {
17
- root?: string,
18
- area?: string,
19
- thumb?: string
20
- }
21
- }
22
-
23
- const props = withDefaults(defineProps<CanvasProps>(), {
24
- type: 'HSV',
25
- height: 208,
26
- width: 208,
27
- })
28
-
29
- const style = computed<CSSProperties>(() => {
30
- return {
31
- position: 'relative',
32
- height: `${props.height}px`,
33
- width: `${props.width}px`,
34
- }
35
- })
36
-
37
- watchEffect(() => {
38
- const ctx = canvasRef.value?.getContext('2d')
39
- if (ctx) {
40
- switch (props.type) {
41
- case 'HSL':
42
- drawHslGradient(ctx, rootContext.hsv.value.h)
43
- break
44
- case 'HSV':
45
- drawHsvGradient(ctx, rootContext.hsv.value.h)
46
- break
47
- }
48
- }
49
- })
50
-
51
- const formatType = computed<'HSV' | 'HSL'>(() => props.type)
52
-
53
- const {
54
- thumbStyles,
55
- handleWheel,
56
- handleKeyDown,
57
- handlePointerDown
58
- } = useThumb(canvasRef, formatType)
59
-
60
- const ui = rootContext.uiSlots('canvas', 'shared')
61
- </script>
62
-
63
- <template>
64
- <div
65
- :style="style"
66
- :class="ui.root(props.ui?.root, props.class)"
67
- @contextmenu.prevent
68
- @wheel="handleWheel"
69
- @keydown="handleKeyDown"
70
- @pointerdown="handlePointerDown"
71
- >
72
- <canvas
73
- ref="canvasRef"
74
- :height="props.height"
75
- :width="props.width"
76
- :class="ui.area(props.ui?.area)"
77
- />
78
- <span
79
- tabindex="0"
80
- :style="thumbStyles"
81
- :class="ui.thumb(props.ui?.thumb)"
82
- />
83
- </div>
84
- </template>
@@ -1,45 +0,0 @@
1
- <script lang="ts" setup>
2
- import { computed } from 'vue'
3
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
4
-
5
- const props = defineProps<{
6
- class?: string
7
- }>()
8
-
9
- const rootContext = injectColorPickerContext()
10
-
11
- const isSupported = computed(() => {
12
- return typeof window !== 'undefined' && !!(window as any).EyeDropper
13
- })
14
-
15
- function openEyeDropper () {
16
- if (!isSupported.value) {
17
- console.warn('EyeDropper API is not available in this environment.')
18
- return
19
- }
20
-
21
- const EyeDropperCtor = (window as any).EyeDropper
22
- const eyeDropper = new EyeDropperCtor()
23
-
24
- eyeDropper
25
- .open()
26
- .then((result: { sRGBHex: string }) => {
27
- rootContext.hexa.value = result.sRGBHex
28
- })
29
- .catch((e: any) => {
30
- console.error(e)
31
- })
32
- }
33
-
34
- const ui = rootContext.uiSlots('dropper')
35
- </script>
36
-
37
- <template>
38
- <button
39
- v-if="isSupported"
40
- :class="ui.base(props.class)"
41
- @click="openEyeDropper"
42
- >
43
- <slot />
44
- </button>
45
- </template>
@@ -1,106 +0,0 @@
1
- <script setup lang="ts">
2
- import type { UiInputSlots } from '../utils/styles'
3
- import { clamp } from '../utils/helpers.ts'
4
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
5
-
6
- const props = defineProps<{
7
- class?: string,
8
- ui?: Partial<UiInputSlots>
9
- }>()
10
-
11
- const rootContext = injectColorPickerContext()
12
-
13
- function parseChannelValue(e: Event, channel: 'h' | 's' | 'v', max: number) {
14
- const target = e.target as HTMLInputElement
15
- const intValue = parseInt(target.value, 10)
16
- const value = isNaN(intValue)
17
- ? rootContext.hsv.value[channel]
18
- : clamp(intValue, 0, max)
19
- if (rootContext.hsv.value[channel] !== value) {
20
- rootContext.hsv.value = {
21
- ...rootContext.hsv.value,
22
- [channel]: channel === 'h' ? value : value / 100
23
- }
24
- rootContext.emitUpdateEnd()
25
- } else {
26
- target.value = channel !== 'h'
27
- ? Math.round(value * 100).toString()
28
- : value.toString()
29
- }
30
- }
31
-
32
- function handleAlphaInput(e: Event) {
33
- const target = e.target as HTMLInputElement
34
- const intValue = parseInt(target.value, 10)
35
- const value = isNaN(intValue)
36
- ? rootContext.alpha.value
37
- : clamp(intValue, 0, 100)
38
- if (rootContext.alpha.value !== value) {
39
- rootContext.alpha.value = value
40
- rootContext.emitUpdateEnd()
41
- } else {
42
- target.value = value.toString()
43
- }
44
- }
45
-
46
- const round = (value: number) => Math.round(value * 100)
47
-
48
- const ui = rootContext.uiSlots('input')
49
- </script>
50
-
51
- <template>
52
- <div :class="ui.group(props.ui?.group, props.class)">
53
- <div :class="ui.item(props.ui?.item)">
54
- <span :class="ui.label(props.ui?.label)">H</span>
55
- <input
56
- type="text"
57
- name="hue"
58
- aria-label="Hue"
59
- :disabled="rootContext.disabled.value"
60
- :class="ui.field(props.ui?.field)"
61
- :value="Math.round(rootContext.hsv.value.h)"
62
- @blur="parseChannelValue($event, 'h', 360)"
63
- />
64
- </div>
65
- <div :class="ui.item(props.ui?.item)">
66
- <span :class="ui.label(props.ui?.label)">S</span>
67
- <input
68
- type="text"
69
- name="saturation"
70
- aria-label="Saturation"
71
- :disabled="rootContext.disabled.value"
72
- :class="ui.field(props.ui?.field)"
73
- :value="round(rootContext.hsv.value.s)"
74
- @blur="parseChannelValue($event, 's', 100)"
75
- />
76
- </div>
77
- <div :class="ui.item(props.ui?.item)">
78
- <span :class="ui.label(props.ui?.label)">B</span>
79
- <input
80
- type="text"
81
- name="brightness"
82
- aria-label="Brightness"
83
- :disabled="rootContext.disabled.value"
84
- :class="ui.field(props.ui?.field)"
85
- :value="round(rootContext.hsv.value.v)"
86
- @blur="parseChannelValue($event, 'v', 100)"
87
- />
88
- </div>
89
- <div
90
- v-if="rootContext.isAlphaEnabled.value"
91
- data-alpha-input
92
- :class="ui.item(props.ui?.item)"
93
- >
94
- <input
95
- type="text"
96
- name="opacity"
97
- aria-label="Opacity"
98
- :value="rootContext.alpha.value"
99
- :disabled="rootContext.disabled.value"
100
- :class="ui.field(props.ui?.field)"
101
- @blur="handleAlphaInput"
102
- />
103
- <span :class="ui.label(props.ui?.label)">%</span>
104
- </div>
105
- </div>
106
- </template>
@@ -1,109 +0,0 @@
1
- <script setup lang="ts">
2
- import type { UiInputSlots } from '../utils/styles'
3
- import { clamp } from '../utils/helpers.ts'
4
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
5
-
6
- const props = defineProps<{
7
- class?: string,
8
- ui?: Partial<UiInputSlots>
9
- }>()
10
-
11
- const rootContext = injectColorPickerContext()
12
-
13
- function parseChannelValue(e: Event, channel: 'h' | 's' | 'l', max: number) {
14
- const target = e.target as HTMLInputElement
15
- const intValue = parseInt(target.value, 10)
16
- const value = isNaN(intValue)
17
- ? rootContext.hsl.value[channel]
18
- : clamp(intValue, 0, max)
19
- if (rootContext.hsl.value[channel] !== value) {
20
- rootContext.hsl.value = {
21
- ...rootContext.hsl.value,
22
- [channel]: channel === 'h' ? value : value / 100
23
- }
24
- rootContext.emitUpdateEnd()
25
- } else {
26
- target.value = channel !== 'h'
27
- ? Math.round(value * 100).toString()
28
- : value.toString()
29
- }
30
- }
31
-
32
- function handleAlphaInput(e: Event) {
33
- const target = e.target as HTMLInputElement
34
- const intValue = parseInt(target.value, 10)
35
- const value = isNaN(intValue)
36
- ? rootContext.alpha.value
37
- : clamp(intValue, 0, 100)
38
- if (rootContext.alpha.value !== value) {
39
- rootContext.alpha.value = value
40
- rootContext.emitUpdateEnd()
41
- } else {
42
- target.value = value.toString()
43
- }
44
- }
45
-
46
- const round = (value: number) => Math.round(value * 100)
47
-
48
- const ui = rootContext.uiSlots('input')
49
- </script>
50
-
51
- <template>
52
- <div :class="ui.group(props.ui?.group, props.class)">
53
- <div :class="ui.item(props.ui?.item)">
54
- <span :class="ui.label(props.ui?.label)">H</span>
55
- <input
56
- type="text"
57
- name="hue"
58
- aria-label="Hue"
59
- :disabled="rootContext.disabled.value"
60
- :class="ui.field(props.ui?.field)"
61
- :value="Math.round(rootContext.hsl.value.h)"
62
- @blur="parseChannelValue($event, 'h', 360)"
63
- />
64
- </div>
65
-
66
- <div :class="ui.item(props.ui?.item)">
67
- <span :class="ui.label(props.ui?.label)">S</span>
68
- <input
69
- type="text"
70
- name="saturation"
71
- aria-label="Saturation"
72
- :disabled="rootContext.disabled.value"
73
- :class="ui.field(props.ui?.field)"
74
- :value="round(rootContext.hsl.value.s)"
75
- @blur="parseChannelValue($event, 's', 100)"
76
- />
77
- </div>
78
-
79
- <div :class="ui.item(props.ui?.item)">
80
- <span :class="ui.label(props.ui?.label)">L</span>
81
- <input
82
- type="text"
83
- name="lightness"
84
- aria-label="Lightness"
85
- :disabled="rootContext.disabled.value"
86
- :class="ui.field(props.ui?.field)"
87
- :value="round(rootContext.hsl.value.l)"
88
- @blur="parseChannelValue($event, 'l', 100)"
89
- />
90
- </div>
91
-
92
- <div
93
- v-if="rootContext.isAlphaEnabled.value"
94
- data-alpha-input
95
- :class="ui.item(props.ui?.item)"
96
- >
97
- <input
98
- type="text"
99
- name="opacity"
100
- aria-label="Opacity"
101
- :value="rootContext.alpha.value"
102
- :disabled="rootContext.disabled.value"
103
- :class="ui.field(props.ui?.field)"
104
- @blur="handleAlphaInput"
105
- />
106
- <span :class="ui.label(props.ui?.label)">%</span>
107
- </div>
108
- </div>
109
- </template>
@@ -1,73 +0,0 @@
1
- <script setup lang="ts">
2
- import type { UiInputSlots } from '../utils/styles'
3
- import { clamp } from '../utils/helpers.ts'
4
- import { parseHex } from '../utils/parsers.ts'
5
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
6
-
7
- const props = defineProps<{
8
- class?: string,
9
- ui?: Partial<UiInputSlots>
10
- }>()
11
-
12
- const rootContext = injectColorPickerContext()
13
-
14
- function handleHexInput(e: Event) {
15
- const target = e.target as HTMLInputElement
16
- const rgbaValue = parseHex(target.value)
17
- if (rgbaValue) {
18
- rootContext.rgba.value = rgbaValue
19
- rootContext.emitUpdateEnd()
20
- } else {
21
- target.value = rootContext.hex.value
22
- }
23
- }
24
-
25
- function handleAlphaInput(e: Event) {
26
- const target = e.target as HTMLInputElement
27
- const intValue = parseInt(target.value, 10)
28
- const value = isNaN(intValue)
29
- ? rootContext.alpha.value
30
- : clamp(intValue, 0, 100)
31
- if (rootContext.alpha.value !== value) {
32
- rootContext.alpha.value = value
33
- rootContext.emitUpdateEnd()
34
- } else {
35
- target.value = value.toString()
36
- }
37
- }
38
-
39
- const ui = rootContext.uiSlots('input')
40
- </script>
41
-
42
- <template>
43
- <div :class="ui.group(props.ui?.group, props.class)">
44
- <div :class="ui.item(props.ui?.item)">
45
- <span :class="ui.label(props.ui?.label)">#</span>
46
- <input
47
- type="text"
48
- name="hex"
49
- aria-label="Hex"
50
- :value="rootContext.hex.value.replace('#', '')"
51
- :disabled="rootContext.disabled.value"
52
- :class="ui.field(props.ui?.field)"
53
- @blur="handleHexInput"
54
- />
55
- </div>
56
- <div
57
- v-if="rootContext.isAlphaEnabled.value"
58
- data-alpha-input
59
- :class="ui.item(props.ui?.item)"
60
- >
61
- <input
62
- type="text"
63
- name="opacity"
64
- aria-label="Opacity"
65
- :value="rootContext.alpha.value"
66
- :disabled="rootContext.disabled.value"
67
- :class="ui.field(props.ui?.field)"
68
- @blur="handleAlphaInput"
69
- />
70
- <span :class="ui.label(props.ui?.label)">%</span>
71
- </div>
72
- </div>
73
- </template>
@@ -1,104 +0,0 @@
1
- <script setup lang="ts">
2
- import type { UiInputSlots } from '../utils/styles'
3
- import { clamp } from '../utils/helpers.ts'
4
- import { injectColorPickerContext } from './ColorPickerRoot.vue'
5
-
6
- const props = defineProps<{
7
- class?: string,
8
- ui?: Partial<UiInputSlots>
9
- }>()
10
-
11
- const rootContext = injectColorPickerContext()
12
-
13
- function parseChannelValue(e: Event, channel: 'r' | 'g' | 'b') {
14
- const target = e.target as HTMLInputElement
15
- const intValue = parseInt(target.value, 10)
16
- const value = isNaN(intValue)
17
- ? rootContext.rgb.value[channel]
18
- : clamp(intValue, 0, 255)
19
- if (rootContext.rgb.value[channel] !== value) {
20
- rootContext.rgb.value = {
21
- ...rootContext.rgb.value,
22
- [channel]: value
23
- }
24
- rootContext.emitUpdateEnd()
25
- } else {
26
- target.value = value.toString()
27
- }
28
- }
29
-
30
- function handleAlphaInput(e: Event) {
31
- const target = e.target as HTMLInputElement
32
- const intValue = parseInt(target.value, 10)
33
- const value = isNaN(intValue)
34
- ? rootContext.alpha.value
35
- : clamp(intValue, 0, 100)
36
- if (rootContext.alpha.value !== value) {
37
- rootContext.alpha.value = value
38
- rootContext.emitUpdateEnd()
39
- } else {
40
- target.value = value.toString()
41
- }
42
- }
43
-
44
- const round = (value: number) => Math.round(value)
45
-
46
- const ui = rootContext.uiSlots('input')
47
- </script>
48
-
49
- <template>
50
- <div :class="ui.group(props.ui?.group, props.class)">
51
- <div :class="ui.item(props.ui?.item)">
52
- <span :class="ui.label(props.ui?.label)">R</span>
53
- <input
54
- type="text"
55
- name="red"
56
- aria-label="Red"
57
- :disabled="rootContext.disabled.value"
58
- :class="ui.field(props.ui?.field)"
59
- :value="round(rootContext.rgb.value.r)"
60
- @blur="parseChannelValue($event, 'r')"
61
- />
62
- </div>
63
- <div :class="ui.item(props.ui?.item)">
64
- <span :class="ui.label(props.ui?.label)">G</span>
65
- <input
66
- type="text"
67
- name="green"
68
- aria-label="Green"
69
- :disabled="rootContext.disabled.value"
70
- :class="ui.field(props.ui?.field)"
71
- :value="round(rootContext.rgb.value.g)"
72
- @blur="parseChannelValue($event, 'g')"
73
- />
74
- </div>
75
- <div :class="ui.item(props.ui?.item)">
76
- <span :class="ui.label(props.ui?.label)">B</span>
77
- <input
78
- type="text"
79
- name="blue"
80
- aria-label="Blue"
81
- :disabled="rootContext.disabled.value"
82
- :class="ui.field(props.ui?.field)"
83
- :value="round(rootContext.rgb.value.b)"
84
- @blur="parseChannelValue($event, 'b')"
85
- />
86
- </div>
87
- <div
88
- v-if="rootContext.isAlphaEnabled.value"
89
- data-alpha-input
90
- :class="ui.item(props.ui?.item)"
91
- >
92
- <input
93
- type="text"
94
- name="opacity"
95
- aria-label="Opacity"
96
- :value="rootContext.alpha.value"
97
- :disabled="rootContext.disabled.value"
98
- :class="ui.field(props.ui?.field)"
99
- @blur="handleAlphaInput"
100
- />
101
- <span :class="ui.label(props.ui?.label)">%</span>
102
- </div>
103
- </div>
104
- </template>