@stroke-stabilizer/vue 0.1.3

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/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # @stroke-stabilizer/vue
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@stroke-stabilizer/vue.svg)](https://www.npmjs.com/package/@stroke-stabilizer/vue)
4
+
5
+ [日本語](./docs/README.ja.md)
6
+
7
+ > This is part of the [stroke-stabilizer](https://github.com/usapopopooon/stroke-stabilizer) monorepo
8
+
9
+ Vue composables for stroke stabilization in digital drawing applications.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @stroke-stabilizer/vue @stroke-stabilizer/core
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### useStabilizedPointer
20
+
21
+ ```vue
22
+ <script setup lang="ts">
23
+ import { useStabilizedPointer } from '@stroke-stabilizer/vue'
24
+
25
+ const { process, reset, pointer } = useStabilizedPointer({
26
+ level: 50,
27
+ onPoint: (point) => {
28
+ draw(point.x, point.y)
29
+ },
30
+ })
31
+
32
+ function handlePointerMove(e: PointerEvent) {
33
+ process({
34
+ x: e.clientX,
35
+ y: e.clientY,
36
+ pressure: e.pressure,
37
+ timestamp: e.timeStamp,
38
+ })
39
+ }
40
+
41
+ function handlePointerUp() {
42
+ reset()
43
+ }
44
+ </script>
45
+
46
+ <template>
47
+ <canvas @pointermove="handlePointerMove" @pointerup="handlePointerUp" />
48
+ </template>
49
+ ```
50
+
51
+ ### With rAF Batch Processing
52
+
53
+ For high-frequency input devices, use the underlying `StabilizedPointer`'s batch processing:
54
+
55
+ ```vue
56
+ <script setup lang="ts">
57
+ import { useStabilizedPointer } from '@stroke-stabilizer/vue'
58
+ import { onMounted, onUnmounted } from 'vue'
59
+
60
+ const { pointer } = useStabilizedPointer({ level: 50 })
61
+
62
+ onMounted(() => {
63
+ pointer.value.enableBatching({
64
+ onBatch: (points) => drawPoints(points),
65
+ })
66
+ })
67
+
68
+ onUnmounted(() => {
69
+ pointer.value.disableBatching()
70
+ })
71
+
72
+ function handlePointerMove(e: PointerEvent) {
73
+ pointer.value.queue({
74
+ x: e.clientX,
75
+ y: e.clientY,
76
+ pressure: e.pressure,
77
+ timestamp: e.timeStamp,
78
+ })
79
+ }
80
+ </script>
81
+
82
+ <template>
83
+ <canvas @pointermove="handlePointerMove" />
84
+ </template>
85
+ ```
86
+
87
+ ### useStabilizationLevel
88
+
89
+ A composable for managing stabilization level with reactive state.
90
+
91
+ ```vue
92
+ <script setup lang="ts">
93
+ import {
94
+ useStabilizationLevel,
95
+ useStabilizedPointer,
96
+ } from '@stroke-stabilizer/vue'
97
+
98
+ const { level, setLevel, isEnabled } = useStabilizationLevel({
99
+ initialLevel: 50,
100
+ onChange: (newLevel) => console.log('Level changed:', newLevel),
101
+ })
102
+
103
+ const { process, reset } = useStabilizedPointer({
104
+ level: level.value,
105
+ })
106
+ </script>
107
+
108
+ <template>
109
+ <div>
110
+ <input
111
+ type="range"
112
+ :min="0"
113
+ :max="100"
114
+ :value="level"
115
+ @input="setLevel(Number(($event.target as HTMLInputElement).value))"
116
+ />
117
+ <span>{{ level }}%</span>
118
+ <span v-if="isEnabled">Stabilization enabled</span>
119
+ </div>
120
+ </template>
121
+ ```
122
+
123
+ ## API
124
+
125
+ ### useStabilizedPointer(options?)
126
+
127
+ Creates a stabilized pointer instance.
128
+
129
+ **Options:**
130
+
131
+ - `level` - Stabilization level (0-100). Uses preset when specified
132
+ - `filters` - Custom filter array. Used when level is not specified
133
+ - `onPoint` - Callback when a point is processed
134
+
135
+ **Returns:**
136
+
137
+ - `process(point)` - Process a single point
138
+ - `processAll(points)` - Process multiple points
139
+ - `flushBuffer()` - Flush internal buffer
140
+ - `reset()` - Reset the pointer state
141
+ - `addFilter(filter)` - Add a filter dynamically
142
+ - `removeFilter(type)` - Remove a filter by type
143
+ - `updateFilter(type, params)` - Update filter parameters
144
+ - `pointer` - Computed ref to the StabilizedPointer instance
145
+ - `filterCount` - Computed ref to the number of active filters
146
+
147
+ ### useStabilizationLevel(options?)
148
+
149
+ Manages stabilization level state.
150
+
151
+ **Options:**
152
+
153
+ - `initialLevel` - Initial level (default: 0)
154
+ - `min` - Minimum level (default: 0)
155
+ - `max` - Maximum level (default: 100)
156
+ - `onChange` - Callback when level changes
157
+
158
+ **Returns:**
159
+
160
+ - `level` - Computed ref to current level
161
+ - `setLevel(value)` - Set the level
162
+ - `increase(amount?)` - Increase level by amount (default: 10)
163
+ - `decrease(amount?)` - Decrease level by amount (default: 10)
164
+ - `isEnabled` - Computed ref indicating if stabilization is active (level > 0)
165
+
166
+ ## License
167
+
168
+ [MIT](../../LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const vue = require("vue");
4
+ const core = require("@stroke-stabilizer/core");
5
+ function useStabilizedPointer(options = {}) {
6
+ const { level, filters, onPoint } = options;
7
+ const pointer = vue.shallowRef(
8
+ level !== void 0 ? core.createStabilizedPointer(level) : (() => {
9
+ const p = new core.StabilizedPointer();
10
+ if (filters) {
11
+ for (const filter of filters) {
12
+ p.addFilter(filter);
13
+ }
14
+ }
15
+ return p;
16
+ })()
17
+ );
18
+ const filterCount = vue.ref(pointer.value.length);
19
+ function process(point) {
20
+ const result = pointer.value.process(point);
21
+ if (result && onPoint) {
22
+ onPoint(result);
23
+ }
24
+ return result;
25
+ }
26
+ function processAll(points) {
27
+ const results = pointer.value.processAll(points);
28
+ if (onPoint) {
29
+ for (const p of results) {
30
+ onPoint(p);
31
+ }
32
+ }
33
+ return results;
34
+ }
35
+ function flushBuffer() {
36
+ return pointer.value.flushBuffer();
37
+ }
38
+ function reset() {
39
+ pointer.value.reset();
40
+ }
41
+ function addFilter(filter) {
42
+ pointer.value.addFilter(filter);
43
+ filterCount.value = pointer.value.length;
44
+ }
45
+ function removeFilter(type) {
46
+ const result = pointer.value.removeFilter(type);
47
+ filterCount.value = pointer.value.length;
48
+ return result;
49
+ }
50
+ function updateFilter(type, params) {
51
+ return pointer.value.updateFilter(type, params);
52
+ }
53
+ if (vue.getCurrentInstance()) {
54
+ vue.onUnmounted(() => {
55
+ pointer.value.clear();
56
+ });
57
+ }
58
+ return {
59
+ process,
60
+ processAll,
61
+ flushBuffer,
62
+ reset,
63
+ addFilter,
64
+ removeFilter,
65
+ updateFilter,
66
+ pointer: vue.computed(() => pointer.value),
67
+ filterCount: vue.computed(() => filterCount.value)
68
+ };
69
+ }
70
+ function useStabilizationLevel(options = {}) {
71
+ const { initialLevel = 0, min = 0, max = 100, onChange } = options;
72
+ const level = vue.ref(Math.max(min, Math.min(max, initialLevel)));
73
+ vue.watch(level, (newValue) => {
74
+ onChange == null ? void 0 : onChange(newValue);
75
+ });
76
+ function setLevel(value) {
77
+ level.value = Math.max(min, Math.min(max, value));
78
+ }
79
+ function increase(amount = 10) {
80
+ setLevel(level.value + amount);
81
+ }
82
+ function decrease(amount = 10) {
83
+ setLevel(level.value - amount);
84
+ }
85
+ return {
86
+ level: vue.computed(() => level.value),
87
+ setLevel,
88
+ increase,
89
+ decrease,
90
+ isEnabled: vue.computed(() => level.value > 0)
91
+ };
92
+ }
93
+ exports.useStabilizationLevel = useStabilizationLevel;
94
+ exports.useStabilizedPointer = useStabilizedPointer;
95
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/useStabilizedPointer.ts","../src/useStabilizationLevel.ts"],"sourcesContent":["import { ref, shallowRef, computed, onUnmounted, getCurrentInstance } from 'vue'\nimport {\n StabilizedPointer,\n createStabilizedPointer,\n type PointerPoint,\n type Filter,\n} from '@stroke-stabilizer/core'\n\nexport interface UseStabilizedPointerOptions {\n /** Stabilization level (0-100). Uses preset when specified */\n level?: number\n /** Custom filters. Used when level is not specified */\n filters?: Filter[]\n /** Callback when a point is processed */\n onPoint?: (point: PointerPoint) => void\n}\n\n/**\n * Vue Composable for stroke stabilization\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useStabilizedPointer } from '@stroke-stabilizer/vue'\n *\n * const { process, reset } = useStabilizedPointer({\n * level: 50,\n * onPoint: (point) => {\n * // Draw with stabilized point\n * drawPoint(point)\n * }\n * })\n *\n * function handlePointerMove(e: PointerEvent) {\n * process({\n * x: e.clientX,\n * y: e.clientY,\n * pressure: e.pressure,\n * timestamp: e.timeStamp\n * })\n * }\n *\n * function handlePointerUp() {\n * reset()\n * }\n * </script>\n *\n * <template>\n * <canvas @pointermove=\"handlePointerMove\" @pointerup=\"handlePointerUp\" />\n * </template>\n * ```\n */\nexport function useStabilizedPointer(\n options: UseStabilizedPointerOptions = {}\n) {\n const { level, filters, onPoint } = options\n\n // StabilizedPointer instance (non-reactive)\n const pointer = shallowRef<StabilizedPointer>(\n level !== undefined\n ? createStabilizedPointer(level)\n : (() => {\n const p = new StabilizedPointer()\n if (filters) {\n for (const filter of filters) {\n p.addFilter(filter)\n }\n }\n return p\n })()\n )\n\n // Filter count (reactive)\n const filterCount = ref(pointer.value.length)\n\n function process(point: PointerPoint): PointerPoint | null {\n const result = pointer.value.process(point)\n if (result && onPoint) {\n onPoint(result)\n }\n return result\n }\n\n function processAll(points: PointerPoint[]): PointerPoint[] {\n const results = pointer.value.processAll(points)\n if (onPoint) {\n for (const p of results) {\n onPoint(p)\n }\n }\n return results\n }\n\n function flushBuffer(): PointerPoint[] {\n return pointer.value.flushBuffer()\n }\n\n function reset(): void {\n pointer.value.reset()\n }\n\n function addFilter(filter: Filter): void {\n pointer.value.addFilter(filter)\n filterCount.value = pointer.value.length\n }\n\n function removeFilter(type: string): boolean {\n const result = pointer.value.removeFilter(type)\n filterCount.value = pointer.value.length\n return result\n }\n\n function updateFilter<T>(type: string, params: Partial<T>): boolean {\n return pointer.value.updateFilter(type, params)\n }\n\n // Cleanup (only register if in component context)\n if (getCurrentInstance()) {\n onUnmounted(() => {\n pointer.value.clear()\n })\n }\n\n return {\n process,\n processAll,\n flushBuffer,\n reset,\n addFilter,\n removeFilter,\n updateFilter,\n pointer: computed(() => pointer.value),\n filterCount: computed(() => filterCount.value),\n }\n}\n","import { ref, computed, watch } from 'vue'\n\nexport interface UseStabilizationLevelOptions {\n /** Initial value (default: 0) */\n initialLevel?: number\n /** Minimum value (default: 0) */\n min?: number\n /** Maximum value (default: 100) */\n max?: number\n /** Callback when level changes */\n onChange?: (level: number) => void\n}\n\n/**\n * Vue Composable for managing stabilization level\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useStabilizationLevel } from '@stroke-stabilizer/vue'\n *\n * const { level, setLevel, isEnabled } = useStabilizationLevel({\n * initialLevel: 50,\n * onChange: (newLevel) => console.log('Level changed:', newLevel)\n * })\n * </script>\n *\n * <template>\n * <div>\n * <input\n * type=\"range\"\n * :min=\"0\"\n * :max=\"100\"\n * :value=\"level\"\n * @input=\"setLevel(Number(($event.target as HTMLInputElement).value))\"\n * />\n * <span>{{ level }}%</span>\n * <span v-if=\"isEnabled\">Stabilization enabled</span>\n * </div>\n * </template>\n * ```\n */\nexport function useStabilizationLevel(\n options: UseStabilizationLevelOptions = {}\n) {\n const { initialLevel = 0, min = 0, max = 100, onChange } = options\n\n const level = ref(Math.max(min, Math.min(max, initialLevel)))\n\n // Watch for changes\n watch(level, (newValue) => {\n onChange?.(newValue)\n })\n\n function setLevel(value: number): void {\n level.value = Math.max(min, Math.min(max, value))\n }\n\n function increase(amount = 10): void {\n setLevel(level.value + amount)\n }\n\n function decrease(amount = 10): void {\n setLevel(level.value - amount)\n }\n\n return {\n level: computed(() => level.value),\n setLevel,\n increase,\n decrease,\n isEnabled: computed(() => level.value > 0),\n }\n}\n"],"names":["shallowRef","createStabilizedPointer","StabilizedPointer","ref","getCurrentInstance","onUnmounted","computed","watch"],"mappings":";;;;AAoDO,SAAS,qBACd,UAAuC,IACvC;AACA,QAAM,EAAE,OAAO,SAAS,QAAA,IAAY;AAGpC,QAAM,UAAUA,IAAAA;AAAAA,IACd,UAAU,SACNC,KAAAA,wBAAwB,KAAK,KAC5B,MAAM;AACL,YAAM,IAAI,IAAIC,uBAAA;AACd,UAAI,SAAS;AACX,mBAAW,UAAU,SAAS;AAC5B,YAAE,UAAU,MAAM;AAAA,QACpB;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAA;AAAA,EAAG;AAIT,QAAM,cAAcC,IAAAA,IAAI,QAAQ,MAAM,MAAM;AAE5C,WAAS,QAAQ,OAA0C;AACzD,UAAM,SAAS,QAAQ,MAAM,QAAQ,KAAK;AAC1C,QAAI,UAAU,SAAS;AACrB,cAAQ,MAAM;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,QAAwC;AAC1D,UAAM,UAAU,QAAQ,MAAM,WAAW,MAAM;AAC/C,QAAI,SAAS;AACX,iBAAW,KAAK,SAAS;AACvB,gBAAQ,CAAC;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,cAA8B;AACrC,WAAO,QAAQ,MAAM,YAAA;AAAA,EACvB;AAEA,WAAS,QAAc;AACrB,YAAQ,MAAM,MAAA;AAAA,EAChB;AAEA,WAAS,UAAU,QAAsB;AACvC,YAAQ,MAAM,UAAU,MAAM;AAC9B,gBAAY,QAAQ,QAAQ,MAAM;AAAA,EACpC;AAEA,WAAS,aAAa,MAAuB;AAC3C,UAAM,SAAS,QAAQ,MAAM,aAAa,IAAI;AAC9C,gBAAY,QAAQ,QAAQ,MAAM;AAClC,WAAO;AAAA,EACT;AAEA,WAAS,aAAgB,MAAc,QAA6B;AAClE,WAAO,QAAQ,MAAM,aAAa,MAAM,MAAM;AAAA,EAChD;AAGA,MAAIC,IAAAA,sBAAsB;AACxBC,QAAAA,YAAY,MAAM;AAChB,cAAQ,MAAM,MAAA;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAASC,IAAAA,SAAS,MAAM,QAAQ,KAAK;AAAA,IACrC,aAAaA,IAAAA,SAAS,MAAM,YAAY,KAAK;AAAA,EAAA;AAEjD;AC5FO,SAAS,sBACd,UAAwC,IACxC;AACA,QAAM,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,KAAK,aAAa;AAE3D,QAAM,QAAQH,IAAAA,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,YAAY,CAAC,CAAC;AAG5DI,YAAM,OAAO,CAAC,aAAa;AACzB,yCAAW;AAAA,EACb,CAAC;AAED,WAAS,SAAS,OAAqB;AACrC,UAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAAA,EAClD;AAEA,WAAS,SAAS,SAAS,IAAU;AACnC,aAAS,MAAM,QAAQ,MAAM;AAAA,EAC/B;AAEA,WAAS,SAAS,SAAS,IAAU;AACnC,aAAS,MAAM,QAAQ,MAAM;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,OAAOD,IAAAA,SAAS,MAAM,MAAM,KAAK;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAWA,IAAAA,SAAS,MAAM,MAAM,QAAQ,CAAC;AAAA,EAAA;AAE7C;;;"}
@@ -0,0 +1,6 @@
1
+ export { useStabilizedPointer } from './useStabilizedPointer';
2
+ export type { UseStabilizedPointerOptions } from './useStabilizedPointer';
3
+ export { useStabilizationLevel } from './useStabilizationLevel';
4
+ export type { UseStabilizationLevelOptions } from './useStabilizationLevel';
5
+ export type { Point, PointerPoint, Filter } from '@stroke-stabilizer/core';
6
+ //# 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,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,YAAY,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AAG3E,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,95 @@
1
+ import { shallowRef, ref, getCurrentInstance, onUnmounted, computed, watch } from "vue";
2
+ import { createStabilizedPointer, StabilizedPointer } from "@stroke-stabilizer/core";
3
+ function useStabilizedPointer(options = {}) {
4
+ const { level, filters, onPoint } = options;
5
+ const pointer = shallowRef(
6
+ level !== void 0 ? createStabilizedPointer(level) : (() => {
7
+ const p = new StabilizedPointer();
8
+ if (filters) {
9
+ for (const filter of filters) {
10
+ p.addFilter(filter);
11
+ }
12
+ }
13
+ return p;
14
+ })()
15
+ );
16
+ const filterCount = ref(pointer.value.length);
17
+ function process(point) {
18
+ const result = pointer.value.process(point);
19
+ if (result && onPoint) {
20
+ onPoint(result);
21
+ }
22
+ return result;
23
+ }
24
+ function processAll(points) {
25
+ const results = pointer.value.processAll(points);
26
+ if (onPoint) {
27
+ for (const p of results) {
28
+ onPoint(p);
29
+ }
30
+ }
31
+ return results;
32
+ }
33
+ function flushBuffer() {
34
+ return pointer.value.flushBuffer();
35
+ }
36
+ function reset() {
37
+ pointer.value.reset();
38
+ }
39
+ function addFilter(filter) {
40
+ pointer.value.addFilter(filter);
41
+ filterCount.value = pointer.value.length;
42
+ }
43
+ function removeFilter(type) {
44
+ const result = pointer.value.removeFilter(type);
45
+ filterCount.value = pointer.value.length;
46
+ return result;
47
+ }
48
+ function updateFilter(type, params) {
49
+ return pointer.value.updateFilter(type, params);
50
+ }
51
+ if (getCurrentInstance()) {
52
+ onUnmounted(() => {
53
+ pointer.value.clear();
54
+ });
55
+ }
56
+ return {
57
+ process,
58
+ processAll,
59
+ flushBuffer,
60
+ reset,
61
+ addFilter,
62
+ removeFilter,
63
+ updateFilter,
64
+ pointer: computed(() => pointer.value),
65
+ filterCount: computed(() => filterCount.value)
66
+ };
67
+ }
68
+ function useStabilizationLevel(options = {}) {
69
+ const { initialLevel = 0, min = 0, max = 100, onChange } = options;
70
+ const level = ref(Math.max(min, Math.min(max, initialLevel)));
71
+ watch(level, (newValue) => {
72
+ onChange == null ? void 0 : onChange(newValue);
73
+ });
74
+ function setLevel(value) {
75
+ level.value = Math.max(min, Math.min(max, value));
76
+ }
77
+ function increase(amount = 10) {
78
+ setLevel(level.value + amount);
79
+ }
80
+ function decrease(amount = 10) {
81
+ setLevel(level.value - amount);
82
+ }
83
+ return {
84
+ level: computed(() => level.value),
85
+ setLevel,
86
+ increase,
87
+ decrease,
88
+ isEnabled: computed(() => level.value > 0)
89
+ };
90
+ }
91
+ export {
92
+ useStabilizationLevel,
93
+ useStabilizedPointer
94
+ };
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/useStabilizedPointer.ts","../src/useStabilizationLevel.ts"],"sourcesContent":["import { ref, shallowRef, computed, onUnmounted, getCurrentInstance } from 'vue'\nimport {\n StabilizedPointer,\n createStabilizedPointer,\n type PointerPoint,\n type Filter,\n} from '@stroke-stabilizer/core'\n\nexport interface UseStabilizedPointerOptions {\n /** Stabilization level (0-100). Uses preset when specified */\n level?: number\n /** Custom filters. Used when level is not specified */\n filters?: Filter[]\n /** Callback when a point is processed */\n onPoint?: (point: PointerPoint) => void\n}\n\n/**\n * Vue Composable for stroke stabilization\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useStabilizedPointer } from '@stroke-stabilizer/vue'\n *\n * const { process, reset } = useStabilizedPointer({\n * level: 50,\n * onPoint: (point) => {\n * // Draw with stabilized point\n * drawPoint(point)\n * }\n * })\n *\n * function handlePointerMove(e: PointerEvent) {\n * process({\n * x: e.clientX,\n * y: e.clientY,\n * pressure: e.pressure,\n * timestamp: e.timeStamp\n * })\n * }\n *\n * function handlePointerUp() {\n * reset()\n * }\n * </script>\n *\n * <template>\n * <canvas @pointermove=\"handlePointerMove\" @pointerup=\"handlePointerUp\" />\n * </template>\n * ```\n */\nexport function useStabilizedPointer(\n options: UseStabilizedPointerOptions = {}\n) {\n const { level, filters, onPoint } = options\n\n // StabilizedPointer instance (non-reactive)\n const pointer = shallowRef<StabilizedPointer>(\n level !== undefined\n ? createStabilizedPointer(level)\n : (() => {\n const p = new StabilizedPointer()\n if (filters) {\n for (const filter of filters) {\n p.addFilter(filter)\n }\n }\n return p\n })()\n )\n\n // Filter count (reactive)\n const filterCount = ref(pointer.value.length)\n\n function process(point: PointerPoint): PointerPoint | null {\n const result = pointer.value.process(point)\n if (result && onPoint) {\n onPoint(result)\n }\n return result\n }\n\n function processAll(points: PointerPoint[]): PointerPoint[] {\n const results = pointer.value.processAll(points)\n if (onPoint) {\n for (const p of results) {\n onPoint(p)\n }\n }\n return results\n }\n\n function flushBuffer(): PointerPoint[] {\n return pointer.value.flushBuffer()\n }\n\n function reset(): void {\n pointer.value.reset()\n }\n\n function addFilter(filter: Filter): void {\n pointer.value.addFilter(filter)\n filterCount.value = pointer.value.length\n }\n\n function removeFilter(type: string): boolean {\n const result = pointer.value.removeFilter(type)\n filterCount.value = pointer.value.length\n return result\n }\n\n function updateFilter<T>(type: string, params: Partial<T>): boolean {\n return pointer.value.updateFilter(type, params)\n }\n\n // Cleanup (only register if in component context)\n if (getCurrentInstance()) {\n onUnmounted(() => {\n pointer.value.clear()\n })\n }\n\n return {\n process,\n processAll,\n flushBuffer,\n reset,\n addFilter,\n removeFilter,\n updateFilter,\n pointer: computed(() => pointer.value),\n filterCount: computed(() => filterCount.value),\n }\n}\n","import { ref, computed, watch } from 'vue'\n\nexport interface UseStabilizationLevelOptions {\n /** Initial value (default: 0) */\n initialLevel?: number\n /** Minimum value (default: 0) */\n min?: number\n /** Maximum value (default: 100) */\n max?: number\n /** Callback when level changes */\n onChange?: (level: number) => void\n}\n\n/**\n * Vue Composable for managing stabilization level\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { useStabilizationLevel } from '@stroke-stabilizer/vue'\n *\n * const { level, setLevel, isEnabled } = useStabilizationLevel({\n * initialLevel: 50,\n * onChange: (newLevel) => console.log('Level changed:', newLevel)\n * })\n * </script>\n *\n * <template>\n * <div>\n * <input\n * type=\"range\"\n * :min=\"0\"\n * :max=\"100\"\n * :value=\"level\"\n * @input=\"setLevel(Number(($event.target as HTMLInputElement).value))\"\n * />\n * <span>{{ level }}%</span>\n * <span v-if=\"isEnabled\">Stabilization enabled</span>\n * </div>\n * </template>\n * ```\n */\nexport function useStabilizationLevel(\n options: UseStabilizationLevelOptions = {}\n) {\n const { initialLevel = 0, min = 0, max = 100, onChange } = options\n\n const level = ref(Math.max(min, Math.min(max, initialLevel)))\n\n // Watch for changes\n watch(level, (newValue) => {\n onChange?.(newValue)\n })\n\n function setLevel(value: number): void {\n level.value = Math.max(min, Math.min(max, value))\n }\n\n function increase(amount = 10): void {\n setLevel(level.value + amount)\n }\n\n function decrease(amount = 10): void {\n setLevel(level.value - amount)\n }\n\n return {\n level: computed(() => level.value),\n setLevel,\n increase,\n decrease,\n isEnabled: computed(() => level.value > 0),\n }\n}\n"],"names":[],"mappings":";;AAoDO,SAAS,qBACd,UAAuC,IACvC;AACA,QAAM,EAAE,OAAO,SAAS,QAAA,IAAY;AAGpC,QAAM,UAAU;AAAA,IACd,UAAU,SACN,wBAAwB,KAAK,KAC5B,MAAM;AACL,YAAM,IAAI,IAAI,kBAAA;AACd,UAAI,SAAS;AACX,mBAAW,UAAU,SAAS;AAC5B,YAAE,UAAU,MAAM;AAAA,QACpB;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAA;AAAA,EAAG;AAIT,QAAM,cAAc,IAAI,QAAQ,MAAM,MAAM;AAE5C,WAAS,QAAQ,OAA0C;AACzD,UAAM,SAAS,QAAQ,MAAM,QAAQ,KAAK;AAC1C,QAAI,UAAU,SAAS;AACrB,cAAQ,MAAM;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,QAAwC;AAC1D,UAAM,UAAU,QAAQ,MAAM,WAAW,MAAM;AAC/C,QAAI,SAAS;AACX,iBAAW,KAAK,SAAS;AACvB,gBAAQ,CAAC;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,cAA8B;AACrC,WAAO,QAAQ,MAAM,YAAA;AAAA,EACvB;AAEA,WAAS,QAAc;AACrB,YAAQ,MAAM,MAAA;AAAA,EAChB;AAEA,WAAS,UAAU,QAAsB;AACvC,YAAQ,MAAM,UAAU,MAAM;AAC9B,gBAAY,QAAQ,QAAQ,MAAM;AAAA,EACpC;AAEA,WAAS,aAAa,MAAuB;AAC3C,UAAM,SAAS,QAAQ,MAAM,aAAa,IAAI;AAC9C,gBAAY,QAAQ,QAAQ,MAAM;AAClC,WAAO;AAAA,EACT;AAEA,WAAS,aAAgB,MAAc,QAA6B;AAClE,WAAO,QAAQ,MAAM,aAAa,MAAM,MAAM;AAAA,EAChD;AAGA,MAAI,sBAAsB;AACxB,gBAAY,MAAM;AAChB,cAAQ,MAAM,MAAA;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,SAAS,MAAM,QAAQ,KAAK;AAAA,IACrC,aAAa,SAAS,MAAM,YAAY,KAAK;AAAA,EAAA;AAEjD;AC5FO,SAAS,sBACd,UAAwC,IACxC;AACA,QAAM,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,KAAK,aAAa;AAE3D,QAAM,QAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,YAAY,CAAC,CAAC;AAG5D,QAAM,OAAO,CAAC,aAAa;AACzB,yCAAW;AAAA,EACb,CAAC;AAED,WAAS,SAAS,OAAqB;AACrC,UAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAAA,EAClD;AAEA,WAAS,SAAS,SAAS,IAAU;AACnC,aAAS,MAAM,QAAQ,MAAM;AAAA,EAC/B;AAEA,WAAS,SAAS,SAAS,IAAU;AACnC,aAAS,MAAM,QAAQ,MAAM;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,OAAO,SAAS,MAAM,MAAM,KAAK;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,SAAS,MAAM,MAAM,QAAQ,CAAC;AAAA,EAAA;AAE7C;"}
@@ -0,0 +1,47 @@
1
+ export interface UseStabilizationLevelOptions {
2
+ /** Initial value (default: 0) */
3
+ initialLevel?: number;
4
+ /** Minimum value (default: 0) */
5
+ min?: number;
6
+ /** Maximum value (default: 100) */
7
+ max?: number;
8
+ /** Callback when level changes */
9
+ onChange?: (level: number) => void;
10
+ }
11
+ /**
12
+ * Vue Composable for managing stabilization level
13
+ *
14
+ * @example
15
+ * ```vue
16
+ * <script setup lang="ts">
17
+ * import { useStabilizationLevel } from '@stroke-stabilizer/vue'
18
+ *
19
+ * const { level, setLevel, isEnabled } = useStabilizationLevel({
20
+ * initialLevel: 50,
21
+ * onChange: (newLevel) => console.log('Level changed:', newLevel)
22
+ * })
23
+ * </script>
24
+ *
25
+ * <template>
26
+ * <div>
27
+ * <input
28
+ * type="range"
29
+ * :min="0"
30
+ * :max="100"
31
+ * :value="level"
32
+ * @input="setLevel(Number(($event.target as HTMLInputElement).value))"
33
+ * />
34
+ * <span>{{ level }}%</span>
35
+ * <span v-if="isEnabled">Stabilization enabled</span>
36
+ * </div>
37
+ * </template>
38
+ * ```
39
+ */
40
+ export declare function useStabilizationLevel(options?: UseStabilizationLevelOptions): {
41
+ level: import("vue").ComputedRef<number>;
42
+ setLevel: (value: number) => void;
43
+ increase: (amount?: number) => void;
44
+ decrease: (amount?: number) => void;
45
+ isEnabled: import("vue").ComputedRef<boolean>;
46
+ };
47
+ //# sourceMappingURL=useStabilizationLevel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStabilizationLevel.d.ts","sourceRoot":"","sources":["../src/useStabilizationLevel.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,4BAA4B;IAC3C,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,4BAAiC;;sBAWjB,MAAM,KAAG,IAAI;mCAIN,IAAI;mCAIJ,IAAI;;EAWrC"}
@@ -0,0 +1,56 @@
1
+ import { StabilizedPointer, type PointerPoint, type Filter } from '@stroke-stabilizer/core';
2
+ export interface UseStabilizedPointerOptions {
3
+ /** Stabilization level (0-100). Uses preset when specified */
4
+ level?: number;
5
+ /** Custom filters. Used when level is not specified */
6
+ filters?: Filter[];
7
+ /** Callback when a point is processed */
8
+ onPoint?: (point: PointerPoint) => void;
9
+ }
10
+ /**
11
+ * Vue Composable for stroke stabilization
12
+ *
13
+ * @example
14
+ * ```vue
15
+ * <script setup lang="ts">
16
+ * import { useStabilizedPointer } from '@stroke-stabilizer/vue'
17
+ *
18
+ * const { process, reset } = useStabilizedPointer({
19
+ * level: 50,
20
+ * onPoint: (point) => {
21
+ * // Draw with stabilized point
22
+ * drawPoint(point)
23
+ * }
24
+ * })
25
+ *
26
+ * function handlePointerMove(e: PointerEvent) {
27
+ * process({
28
+ * x: e.clientX,
29
+ * y: e.clientY,
30
+ * pressure: e.pressure,
31
+ * timestamp: e.timeStamp
32
+ * })
33
+ * }
34
+ *
35
+ * function handlePointerUp() {
36
+ * reset()
37
+ * }
38
+ * </script>
39
+ *
40
+ * <template>
41
+ * <canvas @pointermove="handlePointerMove" @pointerup="handlePointerUp" />
42
+ * </template>
43
+ * ```
44
+ */
45
+ export declare function useStabilizedPointer(options?: UseStabilizedPointerOptions): {
46
+ process: (point: PointerPoint) => PointerPoint | null;
47
+ processAll: (points: PointerPoint[]) => PointerPoint[];
48
+ flushBuffer: () => PointerPoint[];
49
+ reset: () => void;
50
+ addFilter: (filter: Filter) => void;
51
+ removeFilter: (type: string) => boolean;
52
+ updateFilter: <T>(type: string, params: Partial<T>) => boolean;
53
+ pointer: import("vue").ComputedRef<StabilizedPointer>;
54
+ filterCount: import("vue").ComputedRef<number>;
55
+ };
56
+ //# sourceMappingURL=useStabilizedPointer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStabilizedPointer.d.ts","sourceRoot":"","sources":["../src/useStabilizedPointer.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAEjB,KAAK,YAAY,EACjB,KAAK,MAAM,EACZ,MAAM,yBAAyB,CAAA;AAEhC,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,yCAAyC;IACzC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC;qBAsBjB,YAAY,KAAG,YAAY,GAAG,IAAI;yBAQ9B,YAAY,EAAE,KAAG,YAAY,EAAE;uBAUnC,YAAY,EAAE;iBAIpB,IAAI;wBAIK,MAAM,KAAG,IAAI;yBAKZ,MAAM,KAAG,OAAO;mBAMtB,CAAC,QAAQ,MAAM,UAAU,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO;;;EAsBpE"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@stroke-stabilizer/vue",
3
+ "version": "0.1.3",
4
+ "description": "Vue composables for stroke stabilization",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "dev": "vite build --watch",
21
+ "build": "vite build && tsc --emitDeclarationOnly",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "dependencies": {
25
+ "@stroke-stabilizer/core": "workspace:*"
26
+ },
27
+ "peerDependencies": {
28
+ "vue": ">=3.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "vue": "^3.4.0",
32
+ "vite": "^5.4.0",
33
+ "vite-plugin-dts": "^4.0.0"
34
+ },
35
+ "keywords": [
36
+ "vue",
37
+ "composable",
38
+ "stroke",
39
+ "stabilization",
40
+ "drawing",
41
+ "canvas"
42
+ ],
43
+ "author": "usapopopooon <usapopopooon@gmail.com>",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/usapopopooon/stroke-stabilizer"
48
+ },
49
+ "homepage": "https://github.com/usapopopooon/stroke-stabilizer",
50
+ "sideEffects": false
51
+ }